Merge branch 'refactor_knowhere' into 'branch-0.5.0'
MS-565 Refactor knowhere See merge request megasearch/milvus!632 Former-commit-id: bc42aef029e853c270141d5a5727fed0c4f624fepull/191/head
|
@ -93,7 +93,7 @@ endif()
|
|||
set(CORE_INCLUDE_DIRS ${CORE_INCLUDE_DIRS} PARENT_SCOPE)
|
||||
|
||||
if(BUILD_UNIT_TEST STREQUAL "ON")
|
||||
# add_subdirectory(test)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
||||
config_summary()
|
||||
|
|
|
@ -8,7 +8,6 @@ link_directories(${CUDA_TOOLKIT_ROOT_DIR}/lib64)
|
|||
include_directories(${CORE_SOURCE_DIR}/knowhere)
|
||||
include_directories(${CORE_SOURCE_DIR}/thirdparty)
|
||||
include_directories(${CORE_SOURCE_DIR}/thirdparty/SPTAG/AnnService)
|
||||
include_directories(${CORE_SOURCE_DIR}/thirdparty/jsoncons-0.126.0/include)
|
||||
|
||||
set(SPTAG_SOURCE_DIR ${CORE_SOURCE_DIR}/thirdparty/SPTAG)
|
||||
file(GLOB HDR_FILES
|
||||
|
@ -55,6 +54,7 @@ set(index_srcs
|
|||
knowhere/index/vector_index/IndexGPUIVFPQ.cpp
|
||||
knowhere/index/vector_index/FaissBaseIndex.cpp
|
||||
knowhere/index/vector_index/helpers/FaissIO.cpp
|
||||
knowhere/index/vector_index/helpers/IndexParameter.cpp
|
||||
)
|
||||
|
||||
set(depend_libs
|
||||
|
@ -117,7 +117,6 @@ set(CORE_INCLUDE_DIRS
|
|||
${CORE_SOURCE_DIR}/knowhere
|
||||
${CORE_SOURCE_DIR}/thirdparty
|
||||
${CORE_SOURCE_DIR}/thirdparty/SPTAG/AnnService
|
||||
${CORE_SOURCE_DIR}/thirdparty/jsoncons-0.126.0/include
|
||||
${ARROW_INCLUDE_DIR}
|
||||
${FAISS_INCLUDE_DIR}
|
||||
${OPENBLAS_INCLUDE_DIR}
|
||||
|
@ -129,8 +128,6 @@ set(CORE_INCLUDE_DIRS ${CORE_INCLUDE_DIRS} PARENT_SCOPE)
|
|||
|
||||
#INSTALL(DIRECTORY
|
||||
# ${CORE_SOURCE_DIR}/include/knowhere
|
||||
# ${CORE_SOURCE_DIR}/thirdparty/jsoncons-0.126.0/include/jsoncons
|
||||
# ${CORE_SOURCE_DIR}/thirdparty/jsoncons-0.126.0/include/jsoncons_ext
|
||||
# ${ARROW_INCLUDE_DIR}/arrow
|
||||
# ${FAISS_PREFIX}/include/faiss
|
||||
# ${OPENBLAS_INCLUDE_DIR}/
|
||||
|
|
|
@ -69,8 +69,7 @@ ConvertToQueryResult(const DatasetPtr &dataset, const Config &config) {
|
|||
auto dimension = tensor->shape()[1];
|
||||
auto rows = tensor->shape()[0];
|
||||
|
||||
auto k = config[META_K].as<int64_t>();
|
||||
std::vector<SPTAG::QueryResult> query_results(rows, SPTAG::QueryResult(nullptr, k, true));
|
||||
std::vector<SPTAG::QueryResult> query_results(rows, SPTAG::QueryResult(nullptr, config->k, true));
|
||||
for (auto i = 0; i < rows; ++i) {
|
||||
query_results[i].SetTarget(&p_data[i * dimension]);
|
||||
}
|
||||
|
|
|
@ -18,15 +18,42 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <jsoncons/json.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace zilliz {
|
||||
namespace knowhere {
|
||||
|
||||
enum class METRICTYPE {
|
||||
INVALID = 0,
|
||||
L2 = 1,
|
||||
IP = 2,
|
||||
};
|
||||
|
||||
using Config = jsoncons::json;
|
||||
// General Config
|
||||
constexpr int64_t INVALID_VALUE = -1;
|
||||
constexpr int64_t DEFAULT_K = INVALID_VALUE;
|
||||
constexpr int64_t DEFAULT_DIM = INVALID_VALUE;
|
||||
constexpr int64_t DEFAULT_GPUID = INVALID_VALUE;
|
||||
constexpr METRICTYPE DEFAULT_TYPE = METRICTYPE::INVALID;
|
||||
|
||||
struct Cfg {
|
||||
METRICTYPE metric_type = DEFAULT_TYPE;
|
||||
int64_t k = DEFAULT_K;
|
||||
int64_t gpu_id = DEFAULT_GPUID;
|
||||
int64_t d = DEFAULT_DIM;
|
||||
|
||||
Cfg(const int64_t &dim,
|
||||
const int64_t &k,
|
||||
const int64_t &gpu_id,
|
||||
METRICTYPE type)
|
||||
: d(dim), k(k), gpu_id(gpu_id), metric_type(type) {}
|
||||
|
||||
Cfg() = default;
|
||||
|
||||
virtual bool
|
||||
CheckValid(){};
|
||||
};
|
||||
using Config = std::shared_ptr<Cfg>;
|
||||
|
||||
} // namespace knowhere
|
||||
} // namespace zilliz
|
||||
|
|
|
@ -36,10 +36,11 @@ namespace zilliz {
|
|||
namespace knowhere {
|
||||
|
||||
IndexModelPtr GPUIVF::Train(const DatasetPtr &dataset, const Config &config) {
|
||||
auto nlist = config["nlist"].as<size_t>();
|
||||
gpu_id_ = config.get_with_default("gpu_id", gpu_id_);
|
||||
auto metric_type = config["metric_type"].as_string() == "L2" ?
|
||||
faiss::METRIC_L2 : faiss::METRIC_INNER_PRODUCT;
|
||||
auto build_cfg = std::dynamic_pointer_cast<IVFCfg>(config);
|
||||
if (build_cfg != nullptr) {
|
||||
build_cfg->CheckValid(); // throw exception
|
||||
}
|
||||
gpu_id_ = build_cfg->gpu_id;
|
||||
|
||||
GETTENSOR(dataset)
|
||||
|
||||
|
@ -48,7 +49,9 @@ IndexModelPtr GPUIVF::Train(const DatasetPtr &dataset, const Config &config) {
|
|||
ResScope rs(temp_resource, gpu_id_, true);
|
||||
faiss::gpu::GpuIndexIVFFlatConfig idx_config;
|
||||
idx_config.device = gpu_id_;
|
||||
faiss::gpu::GpuIndexIVFFlat device_index(temp_resource->faiss_res.get(), dim, nlist, metric_type, idx_config);
|
||||
faiss::gpu::GpuIndexIVFFlat device_index(temp_resource->faiss_res.get(), dim,
|
||||
build_cfg->nlist, GetMetricType(build_cfg->metric_type),
|
||||
idx_config);
|
||||
device_index.train(rows, (float *) p_data);
|
||||
|
||||
std::shared_ptr<faiss::Index> host_index = nullptr;
|
||||
|
@ -143,9 +146,10 @@ void GPUIVF::search_impl(int64_t n,
|
|||
const Config &cfg) {
|
||||
std::lock_guard<std::mutex> lk(mutex_);
|
||||
|
||||
// TODO(linxj): gpu index support GenParams
|
||||
if (auto device_index = std::static_pointer_cast<faiss::gpu::GpuIndexIVF>(index_)) {
|
||||
auto nprobe = cfg.get_with_default("nprobe", size_t(1));
|
||||
device_index->setNumProbes(nprobe);
|
||||
auto search_cfg = std::dynamic_pointer_cast<IVFCfg>(cfg);
|
||||
device_index->setNumProbes(search_cfg->nprobe);
|
||||
|
||||
{
|
||||
// TODO(linxj): allocate mem
|
||||
|
|
|
@ -29,19 +29,19 @@ namespace zilliz {
|
|||
namespace knowhere {
|
||||
|
||||
IndexModelPtr GPUIVFPQ::Train(const DatasetPtr &dataset, const Config &config) {
|
||||
auto nlist = config["nlist"].as<size_t>();
|
||||
auto M = config["M"].as<size_t>(); // number of subquantizers(subvectors)
|
||||
auto nbits = config["nbits"].as<size_t>();// number of bit per subvector index
|
||||
auto gpu_num = config.get_with_default("gpu_id", gpu_id_);
|
||||
auto metric_type = config["metric_type"].as_string() == "L2" ?
|
||||
faiss::METRIC_L2 : faiss::METRIC_L2; // IP not support.
|
||||
auto build_cfg = std::dynamic_pointer_cast<IVFPQCfg>(config);
|
||||
if (build_cfg != nullptr) {
|
||||
build_cfg->CheckValid(); // throw exception
|
||||
}
|
||||
gpu_id_ = build_cfg->gpu_id;
|
||||
|
||||
GETTENSOR(dataset)
|
||||
|
||||
// TODO(linxj): set device here.
|
||||
// TODO(linxj): set gpu resource here.
|
||||
faiss::gpu::StandardGpuResources res;
|
||||
faiss::gpu::GpuIndexIVFPQ device_index(&res, dim, nlist, M, nbits, metric_type);
|
||||
faiss::gpu::GpuIndexIVFPQ device_index(&res, dim, build_cfg->nlist, build_cfg->m,
|
||||
build_cfg->nbits, GetMetricType(build_cfg->metric_type)); // IP not support
|
||||
device_index.train(rows, (float *) p_data);
|
||||
|
||||
std::shared_ptr<faiss::Index> host_index = nullptr;
|
||||
|
@ -52,10 +52,11 @@ IndexModelPtr GPUIVFPQ::Train(const DatasetPtr &dataset, const Config &config) {
|
|||
|
||||
std::shared_ptr<faiss::IVFSearchParameters> GPUIVFPQ::GenParams(const Config &config) {
|
||||
auto params = std::make_shared<faiss::IVFPQSearchParameters>();
|
||||
params->nprobe = config.get_with_default("nprobe", size_t(1));
|
||||
//params->scan_table_threshold = 0;
|
||||
//params->polysemous_ht = 0;
|
||||
//params->max_codes = 0;
|
||||
auto search_cfg = std::dynamic_pointer_cast<IVFPQCfg>(config);
|
||||
params->nprobe = search_cfg->nprobe;
|
||||
// params->scan_table_threshold = conf->scan_table_threhold;
|
||||
// params->polysemous_ht = conf->polysemous_ht;
|
||||
// params->max_codes = conf->max_codes;
|
||||
|
||||
return params;
|
||||
}
|
||||
|
|
|
@ -28,17 +28,17 @@ namespace zilliz {
|
|||
namespace knowhere {
|
||||
|
||||
IndexModelPtr GPUIVFSQ::Train(const DatasetPtr &dataset, const Config &config) {
|
||||
auto nlist = config["nlist"].as<size_t>();
|
||||
auto nbits = config["nbits"].as<size_t>(); // TODO(linxj): gpu only support SQ4 SQ8 SQ16
|
||||
gpu_id_ = config.get_with_default("gpu_id", gpu_id_);
|
||||
auto metric_type = config["metric_type"].as_string() == "L2" ?
|
||||
faiss::METRIC_L2 : faiss::METRIC_INNER_PRODUCT;
|
||||
auto build_cfg = std::dynamic_pointer_cast<IVFSQCfg>(config);
|
||||
if (build_cfg != nullptr) {
|
||||
build_cfg->CheckValid(); // throw exception
|
||||
}
|
||||
gpu_id_ = build_cfg->gpu_id;
|
||||
|
||||
GETTENSOR(dataset)
|
||||
|
||||
std::stringstream index_type;
|
||||
index_type << "IVF" << nlist << "," << "SQ" << nbits;
|
||||
auto build_index = faiss::index_factory(dim, index_type.str().c_str(), metric_type);
|
||||
index_type << "IVF" << build_cfg->nlist << "," << "SQ" << build_cfg->nbits;
|
||||
auto build_index = faiss::index_factory(dim, index_type.str().c_str(), GetMetricType(build_cfg->metric_type));
|
||||
|
||||
auto temp_resource = FaissGpuResourceMgr::GetInstance().GetRes(gpu_id_);
|
||||
if (temp_resource != nullptr) {
|
||||
|
|
|
@ -51,24 +51,22 @@ DatasetPtr IDMAP::Search(const DatasetPtr &dataset, const Config &config) {
|
|||
KNOWHERE_THROW_MSG("index not initialize");
|
||||
}
|
||||
|
||||
auto k = config["k"].as<size_t>();
|
||||
config->CheckValid();
|
||||
//auto metric_type = config["metric_type"].as_string() == "L2" ?
|
||||
// faiss::METRIC_L2 : faiss::METRIC_INNER_PRODUCT;
|
||||
//index_->metric_type = metric_type;
|
||||
|
||||
GETTENSOR(dataset)
|
||||
|
||||
// TODO(linxj): handle malloc exception
|
||||
auto elems = rows * k;
|
||||
auto elems = rows * config->k;
|
||||
auto res_ids = (int64_t *) malloc(sizeof(int64_t) * elems);
|
||||
auto res_dis = (float *) malloc(sizeof(float) * elems);
|
||||
|
||||
search_impl(rows, (float *) p_data, k, res_dis, res_ids, Config());
|
||||
search_impl(rows, (float *) p_data, config->k, res_dis, res_ids, Config());
|
||||
|
||||
auto id_buf = MakeMutableBufferSmart((uint8_t *) res_ids, sizeof(int64_t) * elems);
|
||||
auto dist_buf = MakeMutableBufferSmart((uint8_t *) res_dis, sizeof(float) * elems);
|
||||
|
||||
// TODO: magic
|
||||
std::vector<BufferPtr> id_bufs{nullptr, id_buf};
|
||||
std::vector<BufferPtr> dist_bufs{nullptr, dist_buf};
|
||||
|
||||
|
@ -136,11 +134,9 @@ int64_t *IDMAP::GetRawIds() {
|
|||
|
||||
const char* type = "IDMap,Flat";
|
||||
void IDMAP::Train(const Config &config) {
|
||||
auto metric_type = config["metric_type"].as_string() == "L2" ?
|
||||
faiss::METRIC_L2 : faiss::METRIC_INNER_PRODUCT;
|
||||
auto dim = config["dim"].as<size_t>();
|
||||
config->CheckValid();
|
||||
|
||||
auto index = faiss::index_factory(dim, type, metric_type);
|
||||
auto index = faiss::index_factory(config->d, type, GetMetricType(config->metric_type));
|
||||
index_.reset(index);
|
||||
}
|
||||
|
||||
|
|
|
@ -37,17 +37,20 @@ namespace knowhere {
|
|||
|
||||
|
||||
IndexModelPtr IVF::Train(const DatasetPtr &dataset, const Config &config) {
|
||||
auto nlist = config["nlist"].as<size_t>();
|
||||
auto metric_type = config["metric_type"].as_string() == "L2" ?
|
||||
faiss::METRIC_L2 : faiss::METRIC_INNER_PRODUCT;
|
||||
auto build_cfg = std::dynamic_pointer_cast<IVFCfg>(config);
|
||||
if (build_cfg != nullptr) {
|
||||
build_cfg->CheckValid(); // throw exception
|
||||
}
|
||||
|
||||
GETTENSOR(dataset)
|
||||
|
||||
faiss::Index *coarse_quantizer = new faiss::IndexFlatL2(dim);
|
||||
auto index = std::make_shared<faiss::IndexIVFFlat>(coarse_quantizer, dim, nlist, metric_type);
|
||||
auto index = std::make_shared<faiss::IndexIVFFlat>(coarse_quantizer, dim,
|
||||
build_cfg->nlist,
|
||||
GetMetricType(build_cfg->metric_type));
|
||||
index->train(rows, (float *) p_data);
|
||||
|
||||
// TODO: override here. train return model or not.
|
||||
// TODO(linxj): override here. train return model or not.
|
||||
return std::make_shared<IVFIndexModel>(index);
|
||||
}
|
||||
|
||||
|
@ -60,7 +63,6 @@ void IVF::Add(const DatasetPtr &dataset, const Config &config) {
|
|||
std::lock_guard<std::mutex> lk(mutex_);
|
||||
GETTENSOR(dataset)
|
||||
|
||||
// TODO: magic here.
|
||||
auto array = dataset->array()[0];
|
||||
auto p_ids = array->data()->GetValues<long>(1, 0);
|
||||
index_->add_with_ids(rows, (float *) p_data, p_ids);
|
||||
|
@ -97,28 +99,22 @@ DatasetPtr IVF::Search(const DatasetPtr &dataset, const Config &config) {
|
|||
KNOWHERE_THROW_MSG("index not initialize or trained");
|
||||
}
|
||||
|
||||
auto k = config["k"].as<size_t>();
|
||||
auto search_cfg = std::dynamic_pointer_cast<IVFCfg>(config);
|
||||
if (search_cfg != nullptr) {
|
||||
search_cfg->CheckValid(); // throw exception
|
||||
}
|
||||
|
||||
GETTENSOR(dataset)
|
||||
|
||||
// TODO(linxj): handle malloc exception
|
||||
auto elems = rows * k;
|
||||
auto elems = rows * search_cfg->k;
|
||||
auto res_ids = (int64_t *) malloc(sizeof(int64_t) * elems);
|
||||
auto res_dis = (float *) malloc(sizeof(float) * elems);
|
||||
|
||||
search_impl(rows, (float*) p_data, k, res_dis, res_ids, config);
|
||||
//faiss::ivflib::search_with_parameters(index_.get(),
|
||||
// rows,
|
||||
// (float *) p_data,
|
||||
// k,
|
||||
// res_dis,
|
||||
// res_ids,
|
||||
// params.get());
|
||||
search_impl(rows, (float*) p_data, search_cfg->k, res_dis, res_ids, config);
|
||||
|
||||
auto id_buf = MakeMutableBufferSmart((uint8_t *) res_ids, sizeof(int64_t) * elems);
|
||||
auto dist_buf = MakeMutableBufferSmart((uint8_t *) res_dis, sizeof(float) * elems);
|
||||
|
||||
// TODO: magic
|
||||
std::vector<BufferPtr> id_bufs{nullptr, id_buf};
|
||||
std::vector<BufferPtr> dist_bufs{nullptr, dist_buf};
|
||||
|
||||
|
@ -146,7 +142,9 @@ void IVF::set_index_model(IndexModelPtr model) {
|
|||
|
||||
std::shared_ptr<faiss::IVFSearchParameters> IVF::GenParams(const Config &config) {
|
||||
auto params = std::make_shared<faiss::IVFPQSearchParameters>();
|
||||
params->nprobe = config.get_with_default("nprobe", size_t(1));
|
||||
|
||||
auto search_cfg = std::dynamic_pointer_cast<IVFCfg>(config);
|
||||
params->nprobe = search_cfg->nprobe;
|
||||
//params->max_codes = config.get_with_default("max_codes", size_t(0));
|
||||
|
||||
return params;
|
||||
|
|
|
@ -27,16 +27,16 @@ namespace zilliz {
|
|||
namespace knowhere {
|
||||
|
||||
IndexModelPtr IVFPQ::Train(const DatasetPtr &dataset, const Config &config) {
|
||||
auto nlist = config["nlist"].as<size_t>();
|
||||
auto M = config["M"].as<size_t>(); // number of subquantizers(subvector)
|
||||
auto nbits = config["nbits"].as<size_t>();// number of bit per subvector index
|
||||
auto metric_type = config["metric_type"].as_string() == "L2" ?
|
||||
faiss::METRIC_L2 : faiss::METRIC_INNER_PRODUCT;
|
||||
auto build_cfg = std::dynamic_pointer_cast<IVFPQCfg>(config);
|
||||
if (build_cfg != nullptr) {
|
||||
build_cfg->CheckValid(); // throw exception
|
||||
}
|
||||
|
||||
GETTENSOR(dataset)
|
||||
|
||||
faiss::Index *coarse_quantizer = new faiss::IndexFlat(dim, metric_type);
|
||||
auto index = std::make_shared<faiss::IndexIVFPQ>(coarse_quantizer, dim, nlist, M, nbits);
|
||||
faiss::Index *coarse_quantizer = new faiss::IndexFlat(dim, GetMetricType(build_cfg->metric_type));
|
||||
auto index = std::make_shared<faiss::IndexIVFPQ>(coarse_quantizer, dim,
|
||||
build_cfg->nlist, build_cfg->m, build_cfg->nbits);
|
||||
index->train(rows, (float *) p_data);
|
||||
|
||||
return std::make_shared<IVFIndexModel>(index);
|
||||
|
@ -44,10 +44,11 @@ IndexModelPtr IVFPQ::Train(const DatasetPtr &dataset, const Config &config) {
|
|||
|
||||
std::shared_ptr<faiss::IVFSearchParameters> IVFPQ::GenParams(const Config &config) {
|
||||
auto params = std::make_shared<faiss::IVFPQSearchParameters>();
|
||||
params->nprobe = config.get_with_default("nprobe", size_t(1));
|
||||
//params->scan_table_threshold = 0;
|
||||
//params->polysemous_ht = 0;
|
||||
//params->max_codes = 0;
|
||||
auto search_cfg = std::dynamic_pointer_cast<IVFPQCfg>(config);
|
||||
params->nprobe = search_cfg->nprobe;
|
||||
// params->scan_table_threshold = conf->scan_table_threhold;
|
||||
// params->polysemous_ht = conf->polysemous_ht;
|
||||
// params->max_codes = conf->max_codes;
|
||||
|
||||
return params;
|
||||
}
|
||||
|
|
|
@ -29,16 +29,17 @@ namespace zilliz {
|
|||
namespace knowhere {
|
||||
|
||||
IndexModelPtr IVFSQ::Train(const DatasetPtr &dataset, const Config &config) {
|
||||
auto nlist = config["nlist"].as<size_t>();
|
||||
auto nbits = config["nbits"].as<size_t>(); // TODO(linxj): only support SQ4 SQ6 SQ8 SQ16
|
||||
auto metric_type = config["metric_type"].as_string() == "L2" ?
|
||||
faiss::METRIC_L2 : faiss::METRIC_INNER_PRODUCT;
|
||||
auto build_cfg = std::dynamic_pointer_cast<IVFSQCfg>(config);
|
||||
if (build_cfg != nullptr) {
|
||||
build_cfg->CheckValid(); // throw exception
|
||||
}
|
||||
|
||||
GETTENSOR(dataset)
|
||||
|
||||
std::stringstream index_type;
|
||||
index_type << "IVF" << nlist << "," << "SQ" << nbits;
|
||||
auto build_index = faiss::index_factory(dim, index_type.str().c_str(), metric_type);
|
||||
index_type << "IVF" << build_cfg->nlist << "," << "SQ" << build_cfg->nbits;
|
||||
auto build_index = faiss::index_factory(dim, index_type.str().c_str(),
|
||||
GetMetricType(build_cfg->metric_type));
|
||||
build_index->train(rows, (float *) p_data);
|
||||
|
||||
std::shared_ptr<faiss::Index> ret_index;
|
||||
|
|
|
@ -118,8 +118,8 @@ CPUKDTRNG::Add(const DatasetPtr &origin, const Config &add_config) {
|
|||
void
|
||||
CPUKDTRNG::SetParameters(const Config &config) {
|
||||
for (auto ¶ : KDTParameterMgr::GetInstance().GetKDTParameters()) {
|
||||
auto value = config.get_with_default(para.first, para.second);
|
||||
index_ptr_->SetParameter(para.first, value);
|
||||
// auto value = config.get_with_default(para.first, para.second);
|
||||
index_ptr_->SetParameter(para.first, para.second);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -67,30 +67,29 @@ void NSG::Load(const BinarySet &index_binary) {
|
|||
}
|
||||
|
||||
DatasetPtr NSG::Search(const DatasetPtr &dataset, const Config &config) {
|
||||
auto build_cfg = std::dynamic_pointer_cast<NSGCfg>(config);
|
||||
if (build_cfg != nullptr) {
|
||||
build_cfg->CheckValid(); // throw exception
|
||||
}
|
||||
|
||||
if (!index_ || !index_->is_trained) {
|
||||
KNOWHERE_THROW_MSG("index not initialize or trained");
|
||||
}
|
||||
|
||||
// Required
|
||||
// if not found throw exception here.
|
||||
auto k = config["k"].as<size_t>();
|
||||
auto search_length = config.get_with_default("search_length", 30);
|
||||
|
||||
GETTENSOR(dataset)
|
||||
|
||||
auto elems = rows * k;
|
||||
auto elems = rows * build_cfg->k;
|
||||
auto res_ids = (int64_t *) malloc(sizeof(int64_t) * elems);
|
||||
auto res_dis = (float *) malloc(sizeof(float) * elems);
|
||||
|
||||
// TODO(linxj): get from config
|
||||
algo::SearchParams s_params;
|
||||
s_params.search_length = search_length;
|
||||
index_->Search((float *) p_data, rows, dim, k, res_dis, res_ids, s_params);
|
||||
s_params.search_length = build_cfg->search_length;
|
||||
index_->Search((float *) p_data, rows, dim,
|
||||
build_cfg->k, res_dis, res_ids, s_params);
|
||||
|
||||
auto id_buf = MakeMutableBufferSmart((uint8_t *) res_ids, sizeof(int64_t) * elems);
|
||||
auto dist_buf = MakeMutableBufferSmart((uint8_t *) res_dis, sizeof(float) * elems);
|
||||
|
||||
// TODO: magic
|
||||
std::vector<BufferPtr> id_bufs{nullptr, id_buf};
|
||||
std::vector<BufferPtr> dist_bufs{nullptr, dist_buf};
|
||||
|
||||
|
@ -108,45 +107,41 @@ DatasetPtr NSG::Search(const DatasetPtr &dataset, const Config &config) {
|
|||
}
|
||||
|
||||
IndexModelPtr NSG::Train(const DatasetPtr &dataset, const Config &config) {
|
||||
TimeRecorder rc("Interface");
|
||||
auto build_cfg = std::dynamic_pointer_cast<NSGCfg>(config);
|
||||
if (build_cfg != nullptr) {
|
||||
build_cfg->CheckValid(); // throw exception
|
||||
}
|
||||
|
||||
auto metric_type = config["metric_type"].as_string();
|
||||
if (metric_type != "L2") { KNOWHERE_THROW_MSG("NSG not support this kind of metric type");}
|
||||
if (build_cfg->metric_type != METRICTYPE::L2) {
|
||||
KNOWHERE_THROW_MSG("NSG not support this kind of metric type");
|
||||
}
|
||||
|
||||
// TODO(linxj): dev IndexFactory, support more IndexType
|
||||
auto preprocess_index = std::make_shared<GPUIVF>(0);
|
||||
//auto preprocess_index = std::make_shared<IVF>();
|
||||
auto preprocess_index = std::make_shared<GPUIVF>(build_cfg->gpu_id);
|
||||
auto model = preprocess_index->Train(dataset, config);
|
||||
preprocess_index->set_index_model(model);
|
||||
preprocess_index->AddWithoutIds(dataset, config);
|
||||
rc.RecordSection("build ivf");
|
||||
|
||||
auto k = config["knng"].as<int64_t>();
|
||||
Graph knng;
|
||||
preprocess_index->GenGraph(k, knng, dataset, config);
|
||||
rc.RecordSection("build knng");
|
||||
preprocess_index->GenGraph(build_cfg->knng, knng, dataset, config);
|
||||
|
||||
algo::BuildParams b_params;
|
||||
b_params.candidate_pool_size = build_cfg->candidate_pool_size;
|
||||
b_params.out_degree = build_cfg->out_degree;
|
||||
b_params.search_length = build_cfg->search_length;
|
||||
|
||||
GETTENSOR(dataset)
|
||||
auto array = dataset->array()[0];
|
||||
auto p_ids = array->data()->GetValues<long>(1, 0);
|
||||
|
||||
algo::BuildParams b_params;
|
||||
b_params.candidate_pool_size = config["candidate_pool_size"].as<size_t>();
|
||||
b_params.out_degree = config["out_degree"].as<size_t>();
|
||||
b_params.search_length = config["search_length"].as<size_t>();
|
||||
|
||||
index_ = std::make_shared<algo::NsgIndex>(dim, rows);
|
||||
index_->SetKnnGraph(knng);
|
||||
index_->Build_with_ids(rows, (float *) p_data, (long *) p_ids, b_params);
|
||||
rc.RecordSection("build nsg");
|
||||
rc.ElapseFromBegin("total cost");
|
||||
return nullptr; // TODO(linxj): support serialize
|
||||
}
|
||||
|
||||
void NSG::Add(const DatasetPtr &dataset, const Config &config) {
|
||||
// TODO(linxj): support incremental index.
|
||||
|
||||
//KNOWHERE_THROW_MSG("Not support yet");
|
||||
// do nothing
|
||||
}
|
||||
|
||||
int64_t NSG::Count() {
|
||||
|
@ -156,6 +151,7 @@ int64_t NSG::Count() {
|
|||
int64_t NSG::Dimension() {
|
||||
return index_->dimension;
|
||||
}
|
||||
|
||||
VectorIndexPtr NSG::Clone() {
|
||||
KNOWHERE_THROW_MSG("not support");
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <memory>
|
||||
|
||||
#include "knowhere/common/Config.h"
|
||||
#include "knowhere/index/vector_index/helpers/IndexParameter.h"
|
||||
#include "knowhere/common/Dataset.h"
|
||||
#include "knowhere/index/Index.h"
|
||||
#include "knowhere/index/preprocessor/Preprocessor.h"
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
|
||||
#include "IndexParameter.h"
|
||||
#include "knowhere/common/Exception.h"
|
||||
|
||||
#include <faiss/Index.h>
|
||||
|
||||
namespace zilliz {
|
||||
namespace knowhere {
|
||||
|
||||
faiss::MetricType GetMetricType(METRICTYPE &type) {
|
||||
if (type == METRICTYPE::L2) return faiss::METRIC_L2;
|
||||
if (type == METRICTYPE::IP) return faiss::METRIC_INNER_PRODUCT;
|
||||
if (type == METRICTYPE::INVALID) KNOWHERE_THROW_MSG("Metric type is invalid");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "knowhere/common/Config.h"
|
||||
#include <faiss/Index.h>
|
||||
|
||||
|
||||
namespace zilliz {
|
||||
namespace knowhere {
|
||||
|
||||
extern faiss::MetricType GetMetricType(METRICTYPE &type);
|
||||
|
||||
// IVF Config
|
||||
constexpr int64_t DEFAULT_NLIST = INVALID_VALUE;
|
||||
constexpr int64_t DEFAULT_NPROBE = INVALID_VALUE;
|
||||
constexpr int64_t DEFAULT_NSUBVECTORS = INVALID_VALUE;
|
||||
constexpr int64_t DEFAULT_NBITS = INVALID_VALUE;
|
||||
constexpr int64_t DEFAULT_SCAN_TABLE_THREHOLD = INVALID_VALUE;
|
||||
constexpr int64_t DEFAULT_POLYSEMOUS_HT = INVALID_VALUE;
|
||||
constexpr int64_t DEFAULT_MAX_CODES = INVALID_VALUE;
|
||||
|
||||
// NSG Config
|
||||
constexpr int64_t DEFAULT_SEARCH_LENGTH = INVALID_VALUE;
|
||||
constexpr int64_t DEFAULT_OUT_DEGREE = INVALID_VALUE;
|
||||
constexpr int64_t DEFAULT_CANDIDATE_SISE = INVALID_VALUE;
|
||||
constexpr int64_t DEFAULT_NNG_K = INVALID_VALUE;
|
||||
|
||||
struct IVFCfg : public Cfg {
|
||||
int64_t nlist = DEFAULT_NLIST;
|
||||
int64_t nprobe = DEFAULT_NPROBE;
|
||||
|
||||
IVFCfg(const int64_t &dim,
|
||||
const int64_t &k,
|
||||
const int64_t &gpu_id,
|
||||
const int64_t &nlist,
|
||||
const int64_t &nprobe,
|
||||
METRICTYPE type)
|
||||
: nlist(nlist), nprobe(nprobe), Cfg(dim, k, gpu_id, type) {}
|
||||
|
||||
IVFCfg() = default;
|
||||
|
||||
bool
|
||||
CheckValid() override {};
|
||||
};
|
||||
using IVFConfig = std::shared_ptr<IVFCfg>;
|
||||
|
||||
struct IVFSQCfg : public IVFCfg {
|
||||
// TODO(linxj): cpu only support SQ4 SQ6 SQ8 SQ16, gpu only support SQ4, SQ8, SQ16
|
||||
int64_t nbits = DEFAULT_NBITS;
|
||||
|
||||
IVFSQCfg(const int64_t &dim,
|
||||
const int64_t &k,
|
||||
const int64_t &gpu_id,
|
||||
const int64_t &nlist,
|
||||
const int64_t &nprobe,
|
||||
const int64_t &nbits,
|
||||
METRICTYPE type)
|
||||
: nbits(nbits), IVFCfg(dim, k, gpu_id, nlist, nprobe, type) {}
|
||||
|
||||
IVFSQCfg() = default;
|
||||
|
||||
bool
|
||||
CheckValid() override {};
|
||||
};
|
||||
using IVFSQConfig = std::shared_ptr<IVFSQCfg>;
|
||||
|
||||
struct IVFPQCfg : public IVFCfg {
|
||||
int64_t m = DEFAULT_NSUBVECTORS; // number of subquantizers(subvector)
|
||||
int64_t nbits = DEFAULT_NBITS; // number of bit per subvector index
|
||||
|
||||
// TODO(linxj): not use yet
|
||||
int64_t scan_table_threhold = DEFAULT_SCAN_TABLE_THREHOLD;
|
||||
int64_t polysemous_ht = DEFAULT_POLYSEMOUS_HT;
|
||||
int64_t max_codes = DEFAULT_MAX_CODES;
|
||||
|
||||
IVFPQCfg(const int64_t &dim,
|
||||
const int64_t &k,
|
||||
const int64_t &gpu_id,
|
||||
const int64_t &nlist,
|
||||
const int64_t &nprobe,
|
||||
const int64_t &nbits,
|
||||
const int64_t &m,
|
||||
METRICTYPE type)
|
||||
: nbits(nbits), m(m), IVFCfg(dim, k, gpu_id, nlist, nprobe, type) {}
|
||||
|
||||
IVFPQCfg() = default;
|
||||
|
||||
bool
|
||||
CheckValid() override {};
|
||||
};
|
||||
using IVFPQConfig = std::shared_ptr<IVFPQCfg>;
|
||||
|
||||
struct NSGCfg : public IVFCfg {
|
||||
int64_t knng = DEFAULT_NNG_K;
|
||||
int64_t search_length = DEFAULT_SEARCH_LENGTH;
|
||||
int64_t out_degree = DEFAULT_OUT_DEGREE;
|
||||
int64_t candidate_pool_size = DEFAULT_CANDIDATE_SISE;
|
||||
|
||||
NSGCfg(const int64_t &dim,
|
||||
const int64_t &k,
|
||||
const int64_t &gpu_id,
|
||||
const int64_t &nlist,
|
||||
const int64_t &nprobe,
|
||||
const int64_t &knng,
|
||||
const int64_t &search_length,
|
||||
const int64_t &out_degree,
|
||||
const int64_t &candidate_size,
|
||||
METRICTYPE type)
|
||||
: knng(knng), search_length(search_length), out_degree(out_degree), candidate_pool_size(candidate_size),
|
||||
IVFCfg(dim, k, gpu_id, nlist, nprobe, type) {}
|
||||
|
||||
NSGCfg() = default;
|
||||
|
||||
bool
|
||||
CheckValid() override {};
|
||||
};
|
||||
using NSGConfig = std::shared_ptr<NSGCfg>;
|
||||
|
||||
struct KDTCfg : public Cfg {
|
||||
int64_t tptnubmber = -1;
|
||||
};
|
||||
|
||||
} // knowhere
|
||||
} // zilliz
|
||||
|
|
@ -35,7 +35,7 @@ KDTParameterMgr::KDTParameterMgr() {
|
|||
{"NumTopDimensionKDTSplit", "5"},
|
||||
{"NumSamplesKDTSplitConsideration", "100"},
|
||||
|
||||
{"TPTNumber", "32"},
|
||||
{"TPTNumber", "1"},
|
||||
{"TPTLeafSize", "2000"},
|
||||
{"NumTopDimensionTPTSplit", "5"},
|
||||
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
include_directories(${CORE_SOURCE_DIR}/thirdparty)
|
||||
include_directories(${CORE_SOURCE_DIR}/thirdparty/SPTAG/AnnService)
|
||||
include_directories(${CORE_SOURCE_DIR}/knowhere)
|
||||
include_directories(${CORE_SOURCE_DIR}/thirdparty/jsoncons-0.126.0/include)
|
||||
include_directories(/usr/local/cuda/include)
|
||||
link_directories(/usr/local/cuda/lib64)
|
||||
link_directories(${CORE_SOURCE_DIR}/thirdparty/tbb)
|
||||
|
||||
set(unittest_libs
|
||||
gtest gmock gtest_main gmock_main)
|
||||
|
||||
message(STATUS "arrow prefix: ${ARROW_PREFIX}")
|
||||
message(STATUS "libjemalloc_pic path: ${ARROW_PREFIX}/lib/libjemalloc_pic.a")
|
||||
|
||||
set(depend_libs
|
||||
gtest gmock gtest_main gmock_main
|
||||
faiss openblas lapack
|
||||
arrow "${ARROW_PREFIX}/lib/libjemalloc_pic.a"
|
||||
tbb
|
||||
|
@ -24,36 +22,45 @@ set(basic_libs
|
|||
|
||||
set(util_srcs
|
||||
${MILVUS_ENGINE_SRC}/utils/easylogging++.cc
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/helpers/FaissGpuResourceMgr.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/helpers/FaissIO.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/helpers/IndexParameter.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/adapter/Structure.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/adapter/ArrowAdapter.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/common/Exception.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/common/Timer.cpp
|
||||
utils.cpp
|
||||
)
|
||||
|
||||
#<IVF-TEST>
|
||||
set(ivf_srcs
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/ivf.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/gpu_ivf.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/cloner.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/idmap.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/adapter/structure.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/common/exception.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/common/timer.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/FaissGpuResourceMgr.cpp
|
||||
utils.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/helpers/Cloner.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/IndexIVF.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/IndexGPUIVF.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/IndexIVFSQ.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/IndexGPUIVFSQ.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/IndexIVFPQ.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/IndexGPUIVFPQ.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/IndexIDMAP.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/FaissBaseIndex.cpp
|
||||
)
|
||||
if(NOT TARGET test_ivf)
|
||||
add_executable(test_ivf test_ivf.cpp ${ivf_srcs} ${util_srcs})
|
||||
endif()
|
||||
target_link_libraries(test_ivf ${depend_libs} ${unittest_libs} ${basic_libs})
|
||||
|
||||
|
||||
#<IDMAP-TEST>
|
||||
set(idmap_srcs
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/idmap.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/ivf.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/cloner.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/gpu_ivf.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/adapter/structure.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/common/exception.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/common/timer.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/FaissGpuResourceMgr.cpp
|
||||
utils.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/helpers/Cloner.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/FaissBaseIndex.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/IndexIDMAP.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/IndexGPUIVF.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/IndexIVF.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/IndexIVFPQ.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/IndexGPUIVFPQ.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/IndexIVFSQ.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/IndexGPUIVFSQ.cpp
|
||||
)
|
||||
if(NOT TARGET test_idmap)
|
||||
add_executable(test_idmap test_idmap.cpp ${idmap_srcs} ${util_srcs})
|
||||
|
@ -62,15 +69,10 @@ target_link_libraries(test_idmap ${depend_libs} ${unittest_libs} ${basic_libs})
|
|||
|
||||
#<KDT-TEST>
|
||||
set(kdt_srcs
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/preprocessor/normalize.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/kdt_parameters.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/cpu_kdt_rng.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/adapter/structure.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/adapter/sptag.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/common/exception.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/adapter/arrow.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/common/timer.cpp
|
||||
utils.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/adapter/SptagAdapter.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/preprocessor/Normalize.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/helpers/KDTParameterMgr.cpp
|
||||
${CORE_SOURCE_DIR}/knowhere/knowhere/index/vector_index/IndexKDT.cpp
|
||||
)
|
||||
if(NOT TARGET test_kdt)
|
||||
add_executable(test_kdt test_kdt.cpp ${kdt_srcs} ${util_srcs})
|
||||
|
|
|
@ -19,17 +19,17 @@
|
|||
#include <gtest/gtest.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "knowhere/index/vector_index/IndexIDMAP.h"
|
||||
#include "knowhere/adapter/Structure.h"
|
||||
#include "knowhere/index/vector_index/utils/Cloner.h"
|
||||
#include "knowhere/index/vector_index/helpers/Cloner.h"
|
||||
#include "knowhere/common/Exception.h"
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
using namespace zilliz::knowhere;
|
||||
using namespace zilliz::knowhere::cloner;
|
||||
|
||||
static int device_id = 0;
|
||||
class IDMAPTest : public DataGen, public ::testing::Test {
|
||||
|
@ -79,15 +79,19 @@ void PrintResult(const DatasetPtr &result,
|
|||
|
||||
TEST_F(IDMAPTest, idmap_basic) {
|
||||
ASSERT_TRUE(!xb.empty());
|
||||
Config Default_cfg;
|
||||
|
||||
index_->Train(Config::object{{"dim", dim}, {"metric_type", "L2"}});
|
||||
index_->Add(base_dataset, Default_cfg);
|
||||
auto conf = std::make_shared<Cfg>();
|
||||
conf->d = dim;
|
||||
conf->k = k;
|
||||
conf->metric_type = METRICTYPE::L2;
|
||||
|
||||
index_->Train(conf);
|
||||
index_->Add(base_dataset, conf);
|
||||
EXPECT_EQ(index_->Count(), nb);
|
||||
EXPECT_EQ(index_->Dimension(), dim);
|
||||
ASSERT_TRUE(index_->GetRawVectors() != nullptr);
|
||||
ASSERT_TRUE(index_->GetRawIds() != nullptr);
|
||||
auto result = index_->Search(query_dataset, Config::object{{"k", k}});
|
||||
auto result = index_->Search(query_dataset, conf);
|
||||
AssertAnns(result, nq, k);
|
||||
PrintResult(result, nq, k);
|
||||
|
||||
|
@ -95,7 +99,7 @@ TEST_F(IDMAPTest, idmap_basic) {
|
|||
auto binaryset = index_->Serialize();
|
||||
auto new_index = std::make_shared<IDMAP>();
|
||||
new_index->Load(binaryset);
|
||||
auto re_result = index_->Search(query_dataset, Config::object{{"k", k}});
|
||||
auto re_result = index_->Search(query_dataset, conf);
|
||||
AssertAnns(re_result, nq, k);
|
||||
PrintResult(re_result, nq, k);
|
||||
}
|
||||
|
@ -109,11 +113,16 @@ TEST_F(IDMAPTest, idmap_serialize) {
|
|||
reader(ret, bin->size);
|
||||
};
|
||||
|
||||
auto conf = std::make_shared<Cfg>();
|
||||
conf->d = dim;
|
||||
conf->k = k;
|
||||
conf->metric_type = METRICTYPE::L2;
|
||||
|
||||
{
|
||||
// serialize index
|
||||
index_->Train(Config::object{{"dim", dim}, {"metric_type", "L2"}});
|
||||
index_->Train(conf);
|
||||
index_->Add(base_dataset, Config());
|
||||
auto re_result = index_->Search(query_dataset, Config::object{{"k", k}});
|
||||
auto re_result = index_->Search(query_dataset, conf);
|
||||
AssertAnns(re_result, nq, k);
|
||||
PrintResult(re_result, nq, k);
|
||||
EXPECT_EQ(index_->Count(), nb);
|
||||
|
@ -133,7 +142,7 @@ TEST_F(IDMAPTest, idmap_serialize) {
|
|||
index_->Load(binaryset);
|
||||
EXPECT_EQ(index_->Count(), nb);
|
||||
EXPECT_EQ(index_->Dimension(), dim);
|
||||
auto result = index_->Search(query_dataset, Config::object{{"k", k}});
|
||||
auto result = index_->Search(query_dataset, conf);
|
||||
AssertAnns(result, nq, k);
|
||||
PrintResult(result, nq, k);
|
||||
}
|
||||
|
@ -141,29 +150,33 @@ TEST_F(IDMAPTest, idmap_serialize) {
|
|||
|
||||
TEST_F(IDMAPTest, copy_test) {
|
||||
ASSERT_TRUE(!xb.empty());
|
||||
Config Default_cfg;
|
||||
|
||||
index_->Train(Config::object{{"dim", dim}, {"metric_type", "L2"}});
|
||||
index_->Add(base_dataset, Default_cfg);
|
||||
auto conf = std::make_shared<Cfg>();
|
||||
conf->d = dim;
|
||||
conf->k = k;
|
||||
conf->metric_type = METRICTYPE::L2;
|
||||
|
||||
index_->Train(conf);
|
||||
index_->Add(base_dataset, conf);
|
||||
EXPECT_EQ(index_->Count(), nb);
|
||||
EXPECT_EQ(index_->Dimension(), dim);
|
||||
ASSERT_TRUE(index_->GetRawVectors() != nullptr);
|
||||
ASSERT_TRUE(index_->GetRawIds() != nullptr);
|
||||
auto result = index_->Search(query_dataset, Config::object{{"k", k}});
|
||||
auto result = index_->Search(query_dataset, conf);
|
||||
AssertAnns(result, nq, k);
|
||||
//PrintResult(result, nq, k);
|
||||
|
||||
{
|
||||
// clone
|
||||
auto clone_index = index_->Clone();
|
||||
auto clone_result = clone_index->Search(query_dataset, Config::object{{"k", k}});
|
||||
auto clone_result = clone_index->Search(query_dataset, conf);
|
||||
AssertAnns(clone_result, nq, k);
|
||||
}
|
||||
|
||||
{
|
||||
// cpu to gpu
|
||||
auto clone_index = CopyCpuToGpu(index_, device_id, Config());
|
||||
auto clone_result = clone_index->Search(query_dataset, Config::object{{"k", k}});
|
||||
auto clone_index = CopyCpuToGpu(index_, device_id, conf);
|
||||
auto clone_result = clone_index->Search(query_dataset, conf);
|
||||
AssertAnns(clone_result, nq, k);
|
||||
ASSERT_THROW({ std::static_pointer_cast<GPUIDMAP>(clone_index)->GetRawVectors(); },
|
||||
zilliz::knowhere::KnowhereException);
|
||||
|
@ -172,24 +185,24 @@ TEST_F(IDMAPTest, copy_test) {
|
|||
|
||||
auto binary = clone_index->Serialize();
|
||||
clone_index->Load(binary);
|
||||
auto new_result = clone_index->Search(query_dataset, Config::object{{"k", k}});
|
||||
auto new_result = clone_index->Search(query_dataset, conf);
|
||||
AssertAnns(new_result, nq, k);
|
||||
|
||||
auto clone_gpu_idx = clone_index->Clone();
|
||||
auto clone_gpu_res = clone_gpu_idx->Search(query_dataset, Config::object{{"k", k}});
|
||||
auto clone_gpu_res = clone_gpu_idx->Search(query_dataset, conf);
|
||||
AssertAnns(clone_gpu_res, nq, k);
|
||||
|
||||
// gpu to cpu
|
||||
auto host_index = CopyGpuToCpu(clone_index, Config());
|
||||
auto host_result = host_index->Search(query_dataset, Config::object{{"k", k}});
|
||||
auto host_index = CopyGpuToCpu(clone_index, conf);
|
||||
auto host_result = host_index->Search(query_dataset, conf);
|
||||
AssertAnns(host_result, nq, k);
|
||||
ASSERT_TRUE(std::static_pointer_cast<IDMAP>(host_index)->GetRawVectors() != nullptr);
|
||||
ASSERT_TRUE(std::static_pointer_cast<IDMAP>(host_index)->GetRawIds() != nullptr);
|
||||
|
||||
// gpu to gpu
|
||||
auto device_index = CopyCpuToGpu(index_, device_id, Config());
|
||||
auto new_device_index = std::static_pointer_cast<GPUIDMAP>(device_index)->CopyGpuToGpu(device_id, Config());
|
||||
auto device_result = new_device_index->Search(query_dataset, Config::object{{"k", k}});
|
||||
auto device_index = CopyCpuToGpu(index_, device_id, conf);
|
||||
auto new_device_index = std::static_pointer_cast<GPUIDMAP>(device_index)->CopyGpuToGpu(device_id, conf);
|
||||
auto device_result = new_device_index->Search(query_dataset, conf);
|
||||
AssertAnns(device_result, nq, k);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,23 +25,32 @@
|
|||
#include <faiss/gpu/GpuAutoTune.h>
|
||||
#include <faiss/gpu/GpuIndexIVFFlat.h>
|
||||
|
||||
#include "knowhere/index/vector_index/IndexGPUIVF.h"
|
||||
#include "knowhere/index/vector_index/IndexIVF.h"
|
||||
#include "knowhere/adapter/Structure.h"
|
||||
#include "knowhere/index/vector_index/utils/Cloner.h"
|
||||
#include "knowhere/common/Exception.h"
|
||||
#include "knowhere/common/Timer.h"
|
||||
#include "knowhere/adapter/Structure.h"
|
||||
#include "knowhere/index/vector_index/helpers/Cloner.h"
|
||||
#include "knowhere/index/vector_index/IndexIVF.h"
|
||||
#include "knowhere/index/vector_index/IndexGPUIVF.h"
|
||||
#include "knowhere/index/vector_index/IndexIVFPQ.h"
|
||||
#include "knowhere/index/vector_index/IndexGPUIVFPQ.h"
|
||||
#include "knowhere/index/vector_index/IndexIVFSQ.h"
|
||||
#include "knowhere/index/vector_index/IndexGPUIVFSQ.h"
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
using namespace zilliz::knowhere;
|
||||
using namespace zilliz::knowhere::cloner;
|
||||
|
||||
using ::testing::TestWithParam;
|
||||
using ::testing::Values;
|
||||
using ::testing::Combine;
|
||||
|
||||
static int device_id = 0;
|
||||
constexpr int device_id = 0;
|
||||
constexpr int64_t DIM = 128;
|
||||
constexpr int64_t NB = 1000000/100;
|
||||
constexpr int64_t NQ = 10;
|
||||
constexpr int64_t K = 10;
|
||||
|
||||
IVFIndexPtr IndexFactory(const std::string &type) {
|
||||
if (type == "IVF") {
|
||||
return std::make_shared<IVF>();
|
||||
|
@ -58,14 +67,67 @@ IVFIndexPtr IndexFactory(const std::string &type) {
|
|||
}
|
||||
}
|
||||
|
||||
enum class ParameterType {
|
||||
ivf,
|
||||
ivfpq,
|
||||
ivfsq,
|
||||
nsg,
|
||||
};
|
||||
|
||||
class ParamGenerator {
|
||||
public:
|
||||
static ParamGenerator& GetInstance(){
|
||||
static ParamGenerator instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
Config Gen(const ParameterType& type){
|
||||
if (type == ParameterType::ivf) {
|
||||
auto tempconf = std::make_shared<IVFCfg>();
|
||||
tempconf->d = DIM;
|
||||
tempconf->gpu_id = device_id;
|
||||
tempconf->nlist = 100;
|
||||
tempconf->nprobe = 16;
|
||||
tempconf->k = K;
|
||||
tempconf->metric_type = METRICTYPE::L2;
|
||||
return tempconf;
|
||||
}
|
||||
else if (type == ParameterType::ivfpq) {
|
||||
auto tempconf = std::make_shared<IVFPQCfg>();
|
||||
tempconf->d = DIM;
|
||||
tempconf->gpu_id = device_id;
|
||||
tempconf->nlist = 100;
|
||||
tempconf->nprobe = 16;
|
||||
tempconf->k = K;
|
||||
tempconf->m = 8;
|
||||
tempconf->nbits = 8;
|
||||
tempconf->metric_type = METRICTYPE::L2;
|
||||
return tempconf;
|
||||
}
|
||||
else if (type == ParameterType::ivfsq) {
|
||||
auto tempconf = std::make_shared<IVFSQCfg>();
|
||||
tempconf->d = DIM;
|
||||
tempconf->gpu_id = device_id;
|
||||
tempconf->nlist = 100;
|
||||
tempconf->nprobe = 16;
|
||||
tempconf->k = K;
|
||||
tempconf->nbits = 8;
|
||||
tempconf->metric_type = METRICTYPE::L2;
|
||||
return tempconf;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class IVFTest
|
||||
: public DataGen, public TestWithParam<::std::tuple<std::string, Config, Config, Config, Config>> {
|
||||
: public DataGen, public TestWithParam<::std::tuple<std::string, ParameterType>> {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
std::tie(index_type, preprocess_cfg, train_cfg, add_cfg, search_cfg) = GetParam();
|
||||
ParameterType parameter_type;
|
||||
std::tie(index_type, parameter_type) = GetParam();
|
||||
//Init_with_default();
|
||||
Generate(128, 1000000/100, 10);
|
||||
Generate(DIM, NB, NQ);
|
||||
index_ = IndexFactory(index_type);
|
||||
conf = ParamGenerator::GetInstance().Gen(parameter_type);
|
||||
FaissGpuResourceMgr::GetInstance().InitDevice(device_id, 1024*1024*200, 1024*1024*600, 2);
|
||||
}
|
||||
void TearDown() override {
|
||||
|
@ -74,46 +136,20 @@ class IVFTest
|
|||
|
||||
protected:
|
||||
std::string index_type;
|
||||
Config preprocess_cfg;
|
||||
Config train_cfg;
|
||||
Config add_cfg;
|
||||
Config search_cfg;
|
||||
Config conf;
|
||||
IVFIndexPtr index_ = nullptr;
|
||||
};
|
||||
|
||||
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(IVFParameters, IVFTest,
|
||||
Values(
|
||||
std::make_tuple("IVF",
|
||||
Config(),
|
||||
Config::object{{"nlist", 100}, {"metric_type", "L2"}},
|
||||
Config(),
|
||||
Config::object{{"k", 10}}),
|
||||
//std::make_tuple("IVFPQ",
|
||||
// Config(),
|
||||
// Config::object{{"nlist", 100}, {"M", 8}, {"nbits", 8}, {"metric_type", "L2"}},
|
||||
// Config(),
|
||||
// Config::object{{"k", 10}}),
|
||||
std::make_tuple("GPUIVF",
|
||||
Config(),
|
||||
Config::object{{"nlist", 100}, {"gpu_id", device_id}, {"metric_type", "L2"}},
|
||||
Config(),
|
||||
Config::object{{"k", 10}}),
|
||||
//std::make_tuple("GPUIVFPQ",
|
||||
// Config(),
|
||||
// Config::object{{"gpu_id", device_id}, {"nlist", 100}, {"M", 8}, {"nbits", 8}, {"metric_type", "L2"}},
|
||||
// Config(),
|
||||
// Config::object{{"k", 10}}),
|
||||
std::make_tuple("IVFSQ",
|
||||
Config(),
|
||||
Config::object{{"nlist", 100}, {"nbits", 8}, {"metric_type", "L2"}},
|
||||
Config(),
|
||||
Config::object{{"k", 10}}),
|
||||
std::make_tuple("GPUIVFSQ",
|
||||
Config(),
|
||||
Config::object{{"gpu_id", device_id}, {"nlist", 100}, {"nbits", 8}, {"metric_type", "L2"}},
|
||||
Config(),
|
||||
Config::object{{"k", 10}})
|
||||
std::make_tuple("IVF", ParameterType::ivf),
|
||||
std::make_tuple("GPUIVF", ParameterType::ivf),
|
||||
// std::make_tuple("IVFPQ", ParameterType::ivfpq),
|
||||
// std::make_tuple("GPUIVFPQ", ParameterType::ivfpq),
|
||||
std::make_tuple("IVFSQ", ParameterType::ivfsq),
|
||||
std::make_tuple("GPUIVFSQ", ParameterType::ivfsq)
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -149,16 +185,16 @@ void PrintResult(const DatasetPtr &result,
|
|||
TEST_P(IVFTest, ivf_basic) {
|
||||
assert(!xb.empty());
|
||||
|
||||
auto preprocessor = index_->BuildPreprocessor(base_dataset, preprocess_cfg);
|
||||
auto preprocessor = index_->BuildPreprocessor(base_dataset, conf);
|
||||
index_->set_preprocessor(preprocessor);
|
||||
|
||||
auto model = index_->Train(base_dataset, train_cfg);
|
||||
auto model = index_->Train(base_dataset, conf);
|
||||
index_->set_index_model(model);
|
||||
index_->Add(base_dataset, add_cfg);
|
||||
index_->Add(base_dataset, conf);
|
||||
EXPECT_EQ(index_->Count(), nb);
|
||||
EXPECT_EQ(index_->Dimension(), dim);
|
||||
auto result = index_->Search(query_dataset, search_cfg);
|
||||
AssertAnns(result, nq, k);
|
||||
auto result = index_->Search(query_dataset, conf);
|
||||
AssertAnns(result, nq, conf->k);
|
||||
//PrintResult(result, nq, k);
|
||||
}
|
||||
|
||||
|
@ -168,20 +204,20 @@ TEST_P(IVFTest, ivf_basic) {
|
|||
// // else
|
||||
// assert(!xb.empty());
|
||||
//
|
||||
// auto preprocessor = index_->BuildPreprocessor(base_dataset, preprocess_cfg);
|
||||
// auto preprocessor = index_->BuildPreprocessor(base_dataset, conf);
|
||||
// index_->set_preprocessor(preprocessor);
|
||||
//
|
||||
// auto model = index_->Train(base_dataset, train_cfg);
|
||||
// auto model = index_->Train(base_dataset, conf);
|
||||
// index_->set_index_model(model);
|
||||
// index_->Add(base_dataset, add_cfg);
|
||||
// index_->Add(base_dataset, conf);
|
||||
// EXPECT_EQ(index_->Count(), nb);
|
||||
// EXPECT_EQ(index_->Dimension(), dim);
|
||||
// auto result = index_->Search(query_dataset, search_cfg);
|
||||
// auto result = index_->Search(query_dataset, conf);
|
||||
// AssertAnns(result, nq, k);
|
||||
//
|
||||
// if (auto device_index = std::dynamic_pointer_cast<GPUIVF>(index_)) {
|
||||
// auto host_index = device_index->Copy_index_gpu_to_cpu();
|
||||
// auto result = host_index->Search(query_dataset, search_cfg);
|
||||
// auto result = host_index->Search(query_dataset, conf);
|
||||
// AssertAnns(result, nq, k);
|
||||
// }
|
||||
//}
|
||||
|
@ -197,7 +233,7 @@ TEST_P(IVFTest, ivf_serialize) {
|
|||
|
||||
{
|
||||
// serialize index-model
|
||||
auto model = index_->Train(base_dataset, train_cfg);
|
||||
auto model = index_->Train(base_dataset, conf);
|
||||
auto binaryset = model->Serialize();
|
||||
auto bin = binaryset.GetByName("IVF");
|
||||
|
||||
|
@ -213,16 +249,16 @@ TEST_P(IVFTest, ivf_serialize) {
|
|||
model->Load(binaryset);
|
||||
|
||||
index_->set_index_model(model);
|
||||
index_->Add(base_dataset, add_cfg);
|
||||
auto result = index_->Search(query_dataset, search_cfg);
|
||||
AssertAnns(result, nq, k);
|
||||
index_->Add(base_dataset, conf);
|
||||
auto result = index_->Search(query_dataset, conf);
|
||||
AssertAnns(result, nq, conf->k);
|
||||
}
|
||||
|
||||
{
|
||||
// serialize index
|
||||
auto model = index_->Train(base_dataset, train_cfg);
|
||||
auto model = index_->Train(base_dataset, conf);
|
||||
index_->set_index_model(model);
|
||||
index_->Add(base_dataset, add_cfg);
|
||||
index_->Add(base_dataset, conf);
|
||||
auto binaryset = index_->Serialize();
|
||||
auto bin = binaryset.GetByName("IVF");
|
||||
|
||||
|
@ -238,24 +274,24 @@ TEST_P(IVFTest, ivf_serialize) {
|
|||
index_->Load(binaryset);
|
||||
EXPECT_EQ(index_->Count(), nb);
|
||||
EXPECT_EQ(index_->Dimension(), dim);
|
||||
auto result = index_->Search(query_dataset, search_cfg);
|
||||
AssertAnns(result, nq, k);
|
||||
auto result = index_->Search(query_dataset, conf);
|
||||
AssertAnns(result, nq, conf->k);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(IVFTest, clone_test) {
|
||||
assert(!xb.empty());
|
||||
|
||||
auto preprocessor = index_->BuildPreprocessor(base_dataset, preprocess_cfg);
|
||||
auto preprocessor = index_->BuildPreprocessor(base_dataset, conf);
|
||||
index_->set_preprocessor(preprocessor);
|
||||
|
||||
auto model = index_->Train(base_dataset, train_cfg);
|
||||
auto model = index_->Train(base_dataset, conf);
|
||||
index_->set_index_model(model);
|
||||
index_->Add(base_dataset, add_cfg);
|
||||
index_->Add(base_dataset, conf);
|
||||
EXPECT_EQ(index_->Count(), nb);
|
||||
EXPECT_EQ(index_->Dimension(), dim);
|
||||
auto result = index_->Search(query_dataset, search_cfg);
|
||||
AssertAnns(result, nq, k);
|
||||
auto result = index_->Search(query_dataset, conf);
|
||||
AssertAnns(result, nq, conf->k);
|
||||
//PrintResult(result, nq, k);
|
||||
|
||||
auto AssertEqual = [&] (DatasetPtr p1, DatasetPtr p2) {
|
||||
|
@ -275,8 +311,8 @@ TEST_P(IVFTest, clone_test) {
|
|||
if (finder != support_idx_vec.cend()) {
|
||||
EXPECT_NO_THROW({
|
||||
auto clone_index = index_->Clone();
|
||||
auto clone_result = clone_index->Search(query_dataset, search_cfg);
|
||||
//AssertAnns(result, nq, k);
|
||||
auto clone_result = clone_index->Search(query_dataset, conf);
|
||||
//AssertAnns(result, nq, conf->k);
|
||||
AssertEqual(result, clone_result);
|
||||
std::cout << "inplace clone [" << index_type << "] success" << std::endl;
|
||||
});
|
||||
|
@ -295,7 +331,7 @@ TEST_P(IVFTest, clone_test) {
|
|||
if (finder != support_idx_vec.cend()) {
|
||||
EXPECT_NO_THROW({
|
||||
auto clone_index = CopyGpuToCpu(index_, Config());
|
||||
auto clone_result = clone_index->Search(query_dataset, search_cfg);
|
||||
auto clone_result = clone_index->Search(query_dataset, conf);
|
||||
AssertEqual(result, clone_result);
|
||||
std::cout << "clone G <=> C [" << index_type << "] success" << std::endl;
|
||||
});
|
||||
|
@ -314,7 +350,7 @@ TEST_P(IVFTest, clone_test) {
|
|||
if (finder != support_idx_vec.cend()) {
|
||||
EXPECT_NO_THROW({
|
||||
auto clone_index = CopyCpuToGpu(index_, device_id, Config());
|
||||
auto clone_result = clone_index->Search(query_dataset, search_cfg);
|
||||
auto clone_result = clone_index->Search(query_dataset, conf);
|
||||
AssertEqual(result, clone_result);
|
||||
std::cout << "clone C <=> G [" << index_type << "] success" << std::endl;
|
||||
});
|
||||
|
@ -338,17 +374,16 @@ TEST_P(IVFTest, seal_test) {
|
|||
|
||||
assert(!xb.empty());
|
||||
|
||||
//index_ = std::make_shared<GPUIVF>(0);
|
||||
auto preprocessor = index_->BuildPreprocessor(base_dataset, preprocess_cfg);
|
||||
auto preprocessor = index_->BuildPreprocessor(base_dataset, conf);
|
||||
index_->set_preprocessor(preprocessor);
|
||||
|
||||
auto model = index_->Train(base_dataset, train_cfg);
|
||||
auto model = index_->Train(base_dataset, conf);
|
||||
index_->set_index_model(model);
|
||||
index_->Add(base_dataset, add_cfg);
|
||||
index_->Add(base_dataset, conf);
|
||||
EXPECT_EQ(index_->Count(), nb);
|
||||
EXPECT_EQ(index_->Dimension(), dim);
|
||||
auto result = index_->Search(query_dataset, search_cfg);
|
||||
AssertAnns(result, nq, k);
|
||||
auto result = index_->Search(query_dataset, conf);
|
||||
AssertAnns(result, nq, conf->k);
|
||||
|
||||
auto cpu_idx = CopyGpuToCpu(index_, Config());
|
||||
|
||||
|
@ -367,13 +402,10 @@ class GPURESTEST
|
|||
: public DataGen, public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
//std::tie(index_type, preprocess_cfg, train_cfg, add_cfg, search_cfg) = GetParam();
|
||||
//Init_with_default();
|
||||
Generate(128, 1000000, 1000);
|
||||
k = 100;
|
||||
//index_ = IndexFactory(index_type);
|
||||
FaissGpuResourceMgr::GetInstance().InitDevice(device_id, 1024*1024*200, 1024*1024*300, 2);
|
||||
|
||||
k = 100;
|
||||
elems = nq * k;
|
||||
ids = (int64_t *) malloc(sizeof(int64_t) * elems);
|
||||
dis = (float *) malloc(sizeof(float) * elems);
|
||||
|
@ -387,10 +419,6 @@ class GPURESTEST
|
|||
|
||||
protected:
|
||||
std::string index_type;
|
||||
Config preprocess_cfg;
|
||||
Config train_cfg;
|
||||
Config add_cfg;
|
||||
Config search_cfg;
|
||||
IVFIndexPtr index_ = nullptr;
|
||||
|
||||
int64_t *ids = nullptr;
|
||||
|
@ -404,26 +432,31 @@ const int load_count = 3;
|
|||
TEST_F(GPURESTEST, gpu_ivf_resource_test) {
|
||||
assert(!xb.empty());
|
||||
|
||||
|
||||
{
|
||||
index_ = std::make_shared<GPUIVF>(-1);
|
||||
ASSERT_EQ(std::dynamic_pointer_cast<GPUIVF>(index_)->GetGpuDevice(), -1);
|
||||
std::dynamic_pointer_cast<GPUIVF>(index_)->SetGpuDevice(device_id);
|
||||
ASSERT_EQ(std::dynamic_pointer_cast<GPUIVF>(index_)->GetGpuDevice(), device_id);
|
||||
|
||||
auto preprocessor = index_->BuildPreprocessor(base_dataset, preprocess_cfg);
|
||||
auto conf = std::make_shared<IVFCfg>();
|
||||
conf->nlist = 1638;
|
||||
conf->d = dim;
|
||||
conf->gpu_id = device_id;
|
||||
conf->metric_type = METRICTYPE::L2;
|
||||
conf->k = k;
|
||||
conf->nprobe = 1;
|
||||
|
||||
auto preprocessor = index_->BuildPreprocessor(base_dataset, conf);
|
||||
index_->set_preprocessor(preprocessor);
|
||||
train_cfg = Config::object{{"nlist", 1638}, {"gpu_id", device_id}, {"metric_type", "L2"}};
|
||||
auto model = index_->Train(base_dataset, train_cfg);
|
||||
auto model = index_->Train(base_dataset, conf);
|
||||
index_->set_index_model(model);
|
||||
index_->Add(base_dataset, add_cfg);
|
||||
index_->Add(base_dataset, conf);
|
||||
EXPECT_EQ(index_->Count(), nb);
|
||||
EXPECT_EQ(index_->Dimension(), dim);
|
||||
|
||||
search_cfg = Config::object{{"k", k}};
|
||||
TimeRecorder tc("knowere GPUIVF");
|
||||
for (int i = 0; i < search_count; ++i) {
|
||||
index_->Search(query_dataset, search_cfg);
|
||||
index_->Search(query_dataset, conf);
|
||||
if (i > search_count - 6 || i < 5)
|
||||
tc.RecordSection("search once");
|
||||
}
|
||||
|
@ -456,14 +489,22 @@ TEST_F(GPURESTEST, gpuivfsq) {
|
|||
// knowhere gpu ivfsq
|
||||
index_type = "GPUIVFSQ";
|
||||
index_ = IndexFactory(index_type);
|
||||
auto preprocessor = index_->BuildPreprocessor(base_dataset, preprocess_cfg);
|
||||
|
||||
auto conf = std::make_shared<IVFSQCfg>();
|
||||
conf->nlist = 1638;
|
||||
conf->d = dim;
|
||||
conf->gpu_id = device_id;
|
||||
conf->metric_type = METRICTYPE::L2;
|
||||
conf->k = k;
|
||||
conf->nbits = 8;
|
||||
conf->nprobe = 1;
|
||||
|
||||
auto preprocessor = index_->BuildPreprocessor(base_dataset, conf);
|
||||
index_->set_preprocessor(preprocessor);
|
||||
train_cfg = Config::object{{"gpu_id", device_id}, {"nlist", 1638}, {"nbits", 8}, {"metric_type", "L2"}};
|
||||
auto model = index_->Train(base_dataset, train_cfg);
|
||||
auto model = index_->Train(base_dataset, conf);
|
||||
index_->set_index_model(model);
|
||||
index_->Add(base_dataset, add_cfg);
|
||||
search_cfg = Config::object{{"k", k}};
|
||||
auto result = index_->Search(query_dataset, search_cfg);
|
||||
index_->Add(base_dataset, conf);
|
||||
auto result = index_->Search(query_dataset, conf);
|
||||
AssertAnns(result, nq, k);
|
||||
|
||||
auto cpu_idx = CopyGpuToCpu(index_, Config());
|
||||
|
@ -473,7 +514,7 @@ TEST_F(GPURESTEST, gpuivfsq) {
|
|||
auto search_idx = CopyCpuToGpu(cpu_idx, device_id, Config());
|
||||
tc.RecordSection("Copy to gpu");
|
||||
for (int i = 0; i < search_count; ++i) {
|
||||
search_idx->Search(query_dataset, search_cfg);
|
||||
search_idx->Search(query_dataset, conf);
|
||||
if (i > search_count - 6 || i < 5)
|
||||
tc.RecordSection("search once");
|
||||
}
|
||||
|
@ -517,20 +558,27 @@ TEST_F(GPURESTEST, gpuivfsq) {
|
|||
}
|
||||
|
||||
TEST_F(GPURESTEST, copyandsearch) {
|
||||
// search and copy at the same time
|
||||
printf("==================\n");
|
||||
|
||||
// search and copy at the same time
|
||||
index_type = "GPUIVFSQ";
|
||||
//index_type = "GPUIVF";
|
||||
index_ = IndexFactory(index_type);
|
||||
auto preprocessor = index_->BuildPreprocessor(base_dataset, preprocess_cfg);
|
||||
|
||||
auto conf = std::make_shared<IVFSQCfg>();
|
||||
conf->nlist = 1638;
|
||||
conf->d = dim;
|
||||
conf->gpu_id = device_id;
|
||||
conf->metric_type = METRICTYPE::L2;
|
||||
conf->k = k;
|
||||
conf->nbits = 8;
|
||||
conf->nprobe = 1;
|
||||
|
||||
auto preprocessor = index_->BuildPreprocessor(base_dataset, conf);
|
||||
index_->set_preprocessor(preprocessor);
|
||||
train_cfg = Config::object{{"gpu_id", device_id}, {"nlist", 1638}, {"nbits", 8}, {"metric_type", "L2"}};
|
||||
auto model = index_->Train(base_dataset, train_cfg);
|
||||
auto model = index_->Train(base_dataset, conf);
|
||||
index_->set_index_model(model);
|
||||
index_->Add(base_dataset, add_cfg);
|
||||
search_cfg = Config::object{{"k", k}};
|
||||
auto result = index_->Search(query_dataset, search_cfg);
|
||||
index_->Add(base_dataset, conf);
|
||||
auto result = index_->Search(query_dataset, conf);
|
||||
AssertAnns(result, nq, k);
|
||||
|
||||
auto cpu_idx = CopyGpuToCpu(index_, Config());
|
||||
|
@ -541,7 +589,7 @@ TEST_F(GPURESTEST, copyandsearch) {
|
|||
auto search_func = [&] {
|
||||
//TimeRecorder tc("search&load");
|
||||
for (int i = 0; i < search_count; ++i) {
|
||||
search_idx->Search(query_dataset, search_cfg);
|
||||
search_idx->Search(query_dataset, conf);
|
||||
//if (i > search_count - 6 || i == 0)
|
||||
// tc.RecordSection("search once");
|
||||
}
|
||||
|
@ -560,7 +608,7 @@ TEST_F(GPURESTEST, copyandsearch) {
|
|||
TimeRecorder tc("basic");
|
||||
CopyCpuToGpu(cpu_idx, device_id, Config());
|
||||
tc.RecordSection("Copy to gpu once");
|
||||
search_idx->Search(query_dataset, search_cfg);
|
||||
search_idx->Search(query_dataset, conf);
|
||||
tc.RecordSection("search once");
|
||||
search_func();
|
||||
tc.RecordSection("only search total");
|
||||
|
@ -576,35 +624,40 @@ TEST_F(GPURESTEST, copyandsearch) {
|
|||
|
||||
TEST_F(GPURESTEST, TrainAndSearch) {
|
||||
index_type = "GPUIVFSQ";
|
||||
//index_type = "GPUIVF";
|
||||
const int train_count = 1;
|
||||
const int search_count = 5000;
|
||||
|
||||
index_ = IndexFactory(index_type);
|
||||
auto preprocessor = index_->BuildPreprocessor(base_dataset, preprocess_cfg);
|
||||
|
||||
auto conf = std::make_shared<IVFSQCfg>();
|
||||
conf->nlist = 1638;
|
||||
conf->d = dim;
|
||||
conf->gpu_id = device_id;
|
||||
conf->metric_type = METRICTYPE::L2;
|
||||
conf->k = k;
|
||||
conf->nbits = 8;
|
||||
conf->nprobe = 1;
|
||||
|
||||
auto preprocessor = index_->BuildPreprocessor(base_dataset, conf);
|
||||
index_->set_preprocessor(preprocessor);
|
||||
train_cfg = Config::object{{"gpu_id", device_id}, {"nlist", 1638}, {"nbits", 8}, {"metric_type", "L2"}};
|
||||
auto model = index_->Train(base_dataset, train_cfg);
|
||||
auto model = index_->Train(base_dataset, conf);
|
||||
auto new_index = IndexFactory(index_type);
|
||||
new_index->set_index_model(model);
|
||||
new_index->Add(base_dataset, add_cfg);
|
||||
new_index->Add(base_dataset, conf);
|
||||
auto cpu_idx = CopyGpuToCpu(new_index, Config());
|
||||
cpu_idx->Seal();
|
||||
auto search_idx = CopyCpuToGpu(cpu_idx, device_id, Config());
|
||||
|
||||
constexpr int train_count = 1;
|
||||
constexpr int search_count = 5000;
|
||||
auto train_stage = [&] {
|
||||
train_cfg = Config::object{{"gpu_id", device_id}, {"nlist", 1638}, {"nbits", 8}, {"metric_type", "L2"}};
|
||||
for (int i = 0; i < train_count; ++i) {
|
||||
auto model = index_->Train(base_dataset, train_cfg);
|
||||
auto model = index_->Train(base_dataset, conf);
|
||||
auto test_idx = IndexFactory(index_type);
|
||||
test_idx->set_index_model(model);
|
||||
test_idx->Add(base_dataset, add_cfg);
|
||||
test_idx->Add(base_dataset, conf);
|
||||
}
|
||||
};
|
||||
auto search_stage = [&](VectorIndexPtr& search_idx) {
|
||||
search_cfg = Config::object{{"k", k}};
|
||||
for (int i = 0; i < search_count; ++i) {
|
||||
auto result = search_idx->Search(query_dataset, search_cfg);
|
||||
auto result = search_idx->Search(query_dataset, conf);
|
||||
AssertAnns(result, nq, k);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -20,10 +20,10 @@
|
|||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include "knowhere/common/Exception.h"
|
||||
|
||||
#include "knowhere/common/Exception.h"
|
||||
#include "knowhere/index/vector_index/IndexKDT.h"
|
||||
#include "knowhere/index/vector_index/utils/Definitions.h"
|
||||
#include "knowhere/index/vector_index/helpers/Definitions.h"
|
||||
#include "knowhere/adapter/SptagAdapter.h"
|
||||
#include "knowhere/adapter/Structure.h"
|
||||
|
||||
|
@ -38,31 +38,24 @@ using ::testing::Combine;
|
|||
|
||||
|
||||
class KDTTest
|
||||
: public DataGen, public TestWithParam<::std::tuple<Config, Config, Config, Config>> {
|
||||
: public DataGen, public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
std::tie(preprocess_cfg, train_cfg, add_cfg, search_cfg) = GetParam();
|
||||
index_ = std::make_shared<CPUKDTRNG>();
|
||||
|
||||
auto tempconf = std::make_shared<KDTCfg>();
|
||||
tempconf->tptnubmber = 1;
|
||||
tempconf->k = 10;
|
||||
conf = tempconf;
|
||||
|
||||
Init_with_default();
|
||||
}
|
||||
|
||||
protected:
|
||||
Config preprocess_cfg;
|
||||
Config train_cfg;
|
||||
Config add_cfg;
|
||||
Config search_cfg;
|
||||
Config conf;
|
||||
std::shared_ptr<CPUKDTRNG> index_ = nullptr;
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(KDTParameters, KDTTest,
|
||||
Values(
|
||||
std::make_tuple(Config(),
|
||||
Config::object{{"TPTNumber", 1}},
|
||||
Config(),
|
||||
Config::object{{"k", 10}})
|
||||
)
|
||||
);
|
||||
|
||||
void AssertAnns(const DatasetPtr &result,
|
||||
const int &nq,
|
||||
const int &k) {
|
||||
|
@ -93,16 +86,16 @@ void PrintResult(const DatasetPtr &result,
|
|||
}
|
||||
|
||||
// TODO(linxj): add test about count() and dimension()
|
||||
TEST_P(KDTTest, kdt_basic) {
|
||||
TEST_F(KDTTest, kdt_basic) {
|
||||
assert(!xb.empty());
|
||||
|
||||
auto preprocessor = index_->BuildPreprocessor(base_dataset, preprocess_cfg);
|
||||
auto preprocessor = index_->BuildPreprocessor(base_dataset, conf);
|
||||
index_->set_preprocessor(preprocessor);
|
||||
|
||||
auto model = index_->Train(base_dataset, train_cfg);
|
||||
auto model = index_->Train(base_dataset, conf);
|
||||
index_->set_index_model(model);
|
||||
index_->Add(base_dataset, add_cfg);
|
||||
auto result = index_->Search(query_dataset, search_cfg);
|
||||
index_->Add(base_dataset, conf);
|
||||
auto result = index_->Search(query_dataset, conf);
|
||||
AssertAnns(result, nq, k);
|
||||
|
||||
{
|
||||
|
@ -124,18 +117,18 @@ TEST_P(KDTTest, kdt_basic) {
|
|||
}
|
||||
}
|
||||
|
||||
TEST_P(KDTTest, kdt_serialize) {
|
||||
TEST_F(KDTTest, kdt_serialize) {
|
||||
assert(!xb.empty());
|
||||
|
||||
auto preprocessor = index_->BuildPreprocessor(base_dataset, preprocess_cfg);
|
||||
auto preprocessor = index_->BuildPreprocessor(base_dataset, conf);
|
||||
index_->set_preprocessor(preprocessor);
|
||||
|
||||
auto model = index_->Train(base_dataset, train_cfg);
|
||||
//index_->Add(base_dataset, add_cfg);
|
||||
auto model = index_->Train(base_dataset, conf);
|
||||
//index_->Add(base_dataset, conf);
|
||||
auto binaryset = index_->Serialize();
|
||||
auto new_index = std::make_shared<CPUKDTRNG>();
|
||||
new_index->Load(binaryset);
|
||||
auto result = new_index->Search(query_dataset, search_cfg);
|
||||
auto result = new_index->Search(query_dataset, conf);
|
||||
AssertAnns(result, nq, k);
|
||||
PrintResult(result, nq, k);
|
||||
ASSERT_EQ(new_index->Count(), nb);
|
||||
|
@ -172,7 +165,7 @@ TEST_P(KDTTest, kdt_serialize) {
|
|||
|
||||
auto new_index = std::make_shared<CPUKDTRNG>();
|
||||
new_index->Load(load_data_list);
|
||||
auto result = new_index->Search(query_dataset, search_cfg);
|
||||
auto result = new_index->Search(query_dataset, conf);
|
||||
AssertAnns(result, nq, k);
|
||||
PrintResult(result, nq, k);
|
||||
}
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
{
|
||||
"targets": {
|
||||
"centos7-x86_64": {
|
||||
"buildenv": "centos7-x86_64",
|
||||
"builddeps": ["gcc-c++", "make", "wget"],
|
||||
"environment": {
|
||||
"CXXFLAGS": "-std=c++11 -Wall -g3"
|
||||
},
|
||||
"buildcmd": [
|
||||
"uname -a",
|
||||
"rpm -q centos-release",
|
||||
"g++ --version",
|
||||
"cd",
|
||||
"wget https://github.com/Kitware/CMake/releases/download/v3.14.0/cmake-3.14.0.tar.gz",
|
||||
"tar xfz cmake-3.14.0.tar.gz",
|
||||
"cd cmake-3.14.0",
|
||||
"./bootstrap",
|
||||
"make -j8",
|
||||
"cd",
|
||||
"cmake-3.14.0/bin/cmake . -DBUILD_TESTS=ON",
|
||||
"cmake-3.14.0/bin/cmake --build . --target test_jsoncons",
|
||||
"cd tests",
|
||||
"./test_jsoncons;"
|
||||
]
|
||||
},
|
||||
"fedora24-x86_64": {
|
||||
"buildenv": "fedora24-x86_64",
|
||||
"builddeps": ["cmake", "make", "gcc gcc-c++"],
|
||||
"environment": {
|
||||
"CXXFLAGS": "-std=c++11 -Wall -g3"
|
||||
},
|
||||
"buildcmd": [
|
||||
"uname -a",
|
||||
"cat /etc/fedora-release",
|
||||
"g++ --version",
|
||||
"cmake . -DBUILD_TESTS=ON",
|
||||
"cmake --build . --target test_jsoncons",
|
||||
"cd tests",
|
||||
"./test_jsoncons;"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
*.suo
|
||||
*.sdf
|
||||
*.VC.opendb
|
||||
*.VC.db
|
||||
*.vcxproj.user
|
||||
*.vcxproj.filters
|
||||
**/x64/Debug/
|
||||
**/x64/Release/
|
||||
**/*.vcxproj
|
||||
**/vs2017
|
||||
**/vs2015
|
||||
**/vs2013
|
||||
**/temp
|
||||
**/build
|
||||
|
||||
examples/build/cmake/build_llvm.sh
|
||||
examples/build/cmake/build_llvm
|
||||
|
||||
src/jsoncons/json_structures.hpp.orig
|
||||
|
||||
examples/build/vs2013/
|
||||
|
||||
src/jsoncons/json_serializer2.hpp
|
||||
|
||||
examples/booklist.json
|
||||
examples/booklist2.json
|
||||
|
||||
examples/build/vs2017/.vs/vs2017/v15/ipch/AutoPCH/2f913b3e9413499/BASICS_EXAMPLES.ipch
|
||||
examples/build/vs2017/.vs/vs2017/v15/ipch/AutoPCH/8571a45cc244269f/EXAMPLES.ipch
|
||||
examples/build/vs2017/vs2017.sln
|
|
@ -1,240 +0,0 @@
|
|||
language: cpp
|
||||
dist: trusty
|
||||
sudo: required
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-4.8
|
||||
- libgmp-dev
|
||||
env: COMPILER=gcc VERSION=4.8 CXXFLAGS="-std=c++11"
|
||||
|
||||
- os: linux
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-4.9
|
||||
- libgmp-dev
|
||||
env: COMPILER=gcc VERSION=4.9 JSONCONS_SANITIZE=1 CXXFLAGS="-std=c++11"
|
||||
|
||||
- os: linux
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-5
|
||||
env: COMPILER=gcc VERSION=5 CXXFLAGS="-std=gnu++11"
|
||||
|
||||
- os: linux
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-6
|
||||
env: COMPILER=gcc VERSION=6 JSONCONS_SANITIZE=1
|
||||
|
||||
- os: linux
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-7
|
||||
env: COMPILER=gcc VERSION=7 JSONCONS_SANITIZE=1
|
||||
|
||||
- os: linux
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-8
|
||||
env: COMPILER=gcc VERSION=8 JSONCONS_SANITIZE=1 CXXFLAGS="-std=c++17 -Werror -Wall -Wextra -Wimplicit-fallthrough -pedantic -Wcast-align -Wcast-qual"
|
||||
|
||||
- os: linux
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-8
|
||||
env: COMPILER=gcc VERSION=8 JSONCONS_SANITIZE=1 CXXFLAGS="-std=c++17 -DJSONCONS_HAS_STRING_VIEW"
|
||||
|
||||
- os: linux
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-8
|
||||
env: COMPILER=gcc VERSION=8 JSONCONS_SANITIZE=1 CXXFLAGS="-std=gnu++17 -Wall -Wextra -Wimplicit-fallthrough"
|
||||
|
||||
- os: linux
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- clang-3.9
|
||||
- g++-4.8-aarch64-linux-gnu
|
||||
- gcc-4.8-aarch64-linux-gnu
|
||||
- g++-4.8-multilib
|
||||
- gcc-4.8-multilib
|
||||
- qemu
|
||||
- qemu-system-arm
|
||||
env: COMPILER=clang VERSION=3.9 CROSS_COMPILE=1 ARM_ARCH_DIR=aarch64-linux-gnu GCC_VER=4.8.4 ARM_SETTINGS="armv8-a -target aarch64-linux-gnueabi" CXXFLAGS="-std=c++11"
|
||||
|
||||
- os: linux
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-4.0
|
||||
packages:
|
||||
- clang-4.0
|
||||
- g++-7
|
||||
env: COMPILER=clang VERSION=4.0 CXXFLAGS="-std=c++11"
|
||||
|
||||
- os: linux
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-5.0
|
||||
packages:
|
||||
- clang-5.0
|
||||
- g++-7
|
||||
env: COMPILER=clang VERSION=5.0 CXXFLAGS="-std=gnu++11"
|
||||
|
||||
- os: linux
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-6.0
|
||||
packages:
|
||||
- clang-6.0
|
||||
- g++-7
|
||||
env: COMPILER=clang VERSION=6.0 JSONCONS_SANITIZE=1 CXXFLAGS="-std=c++11 -Wall -Wextra -Wimplicit-fallthrough"
|
||||
|
||||
- os: linux
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-6.0
|
||||
packages:
|
||||
- clang-6.0
|
||||
- g++-7
|
||||
env: COMPILER=clang VERSION=6.0 CXXFLAGS="-DJSONCONS_NO_DEPRECATED"
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode7.3
|
||||
compiler: clang
|
||||
env: CXXFLAGS="-std=c++11"
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode8
|
||||
compiler: clang
|
||||
env: CXXFLAGS="-std=c++11"
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode8.1
|
||||
compiler: clang
|
||||
env: CXXFLAGS="-std=c++11"
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode8.2
|
||||
compiler: clang
|
||||
env: CXXFLAGS="-std=c++11"
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode8.3
|
||||
compiler: clang
|
||||
env: CXXFLAGS="-std=c++11"
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode9
|
||||
compiler: clang
|
||||
env: CXXFLAGS="-std=c++11"
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode9.1
|
||||
compiler: clang
|
||||
env: CXXFLAGS="-std=c++11"
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode9.2
|
||||
compiler: clang
|
||||
env: CXXFLAGS="-std=c++11"
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode9.3
|
||||
compiler: clang
|
||||
env: CXXFLAGS="-std=c++11"
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode9.4
|
||||
compiler: clang
|
||||
env: CXXFLAGS="-std=c++11"
|
||||
|
||||
before_install:
|
||||
- |
|
||||
# Configure build variables
|
||||
if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
|
||||
if [[ "$COMPILER" == "gcc" ]]; then
|
||||
export CXX=g++-$VERSION CC=gcc-$VERSION;
|
||||
fi
|
||||
if [[ "$COMPILER" == "clang" ]]; then
|
||||
export CXX=clang++-$VERSION CC=clang-$VERSION;
|
||||
fi
|
||||
elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||
export CXX=clang++ CC=clang;
|
||||
fi
|
||||
install:
|
||||
# get CMake (only for systems with brew - macOS)
|
||||
- |
|
||||
if [[ (-x $(which brew)) ]]; then
|
||||
brew update
|
||||
brew install cmake
|
||||
brew upgrade cmake
|
||||
cmake --version
|
||||
fi
|
||||
|
||||
- if [[ "$CROSS_COMPILE" == 1 ]] ; then
|
||||
if [[ "$ARM_ARCH_DIR" == "aarch64-linux-gnu" ]] ; then
|
||||
mkdir $HOME/linker_bin ;
|
||||
ln -s /usr/bin/aarch64-linux-gnu-ld $HOME/linker_bin/ld ;
|
||||
echo "SETTING GNU LINKER DIR" ;
|
||||
ls -al $HOME/linker_bin/ld ;
|
||||
cmake . -DBUILD_TESTS=ON -DCROSS_COMPILE_ARM=ON -DDOWNLOAD_GTEST=ON -DARM_ARCH_DIRECTORY="$ARM_ARCH_DIR" -DARM_GCC_VER="$GCC_VER" -DTARGET_ARCH="$ARM_SETTINGS --prefix=$HOME/linker_bin/" ${CMAKE_OPTIONS};
|
||||
else
|
||||
cmake . -DBUILD_TESTS=ON -DCROSS_COMPILE_ARM=ON -DDOWNLOAD_GTEST=ON -DARM_ARCH_DIRECTORY="$ARM_ARCH_DIR" -DARM_GCC_VER="$GCC_VER" -DTARGET_ARCH="$ARM_SETTINGS" ${CMAKE_OPTIONS};
|
||||
fi
|
||||
else
|
||||
cmake . -DBUILD_TESTS=ON ${CMAKE_OPTIONS};
|
||||
fi
|
||||
- make -j2 test_jsoncons
|
||||
- cd tests
|
||||
script:
|
||||
- if [[ "$JSONCONS_VALGRIND" == 1 ]]; then
|
||||
ctest -T memcheck;
|
||||
fi
|
||||
- if [[ "$CROSS_COMPILE" == 1 ]]; then
|
||||
if [[ "$ARM_ARCH_DIR" == "aarch64-linux-gnu" ]]; then
|
||||
qemu-aarch64 -L /usr/aarch64-linux-gnu/ ./test_jsoncons ;
|
||||
else
|
||||
qemu-arm -L /usr/arm-linux-gnueabi/ ./test_jsoncons ;
|
||||
fi
|
||||
else
|
||||
./test_jsoncons;
|
||||
fi
|
|
@ -1,73 +0,0 @@
|
|||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
project(jsoncons)
|
||||
|
||||
set(JSONCONS_PROJECT_DIR ${PROJECT_SOURCE_DIR})
|
||||
set(JSONCONS_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
# Versioning
|
||||
# ==========
|
||||
|
||||
file(STRINGS "${JSONCONS_INCLUDE_DIR}/jsoncons/config/version.hpp" jsoncons_version_defines
|
||||
REGEX "#define JSONCONS_VERSION_(MAJOR|MINOR|PATCH)")
|
||||
foreach(ver ${jsoncons_version_defines})
|
||||
if(ver MATCHES "#define JSONCONS_VERSION_(MAJOR|MINOR|PATCH) +([^ ]+)$")
|
||||
set(JSONCONS_VERSION_${CMAKE_MATCH_1} "${CMAKE_MATCH_2}" CACHE INTERNAL "")
|
||||
endif()
|
||||
endforeach()
|
||||
set(${PROJECT_NAME}_VERSION
|
||||
${JSONCONS_VERSION_MAJOR}.${JSONCONS_VERSION_MINOR}.${JSONCONS_VERSION_PATCH})
|
||||
message(STATUS "jsoncons v${${PROJECT_NAME}_VERSION}")
|
||||
|
||||
# Build
|
||||
# =====
|
||||
|
||||
|
||||
file(GLOB_RECURSE JSONCONS_HEADERS ${JSONCONS_INCLUDE_DIR}/*.hpp)
|
||||
|
||||
add_library(jsoncons INTERFACE)
|
||||
target_include_directories(jsoncons INTERFACE $<BUILD_INTERFACE:${JSONCONS_INCLUDE_DIR}>
|
||||
$<INSTALL_INTERFACE:include>)
|
||||
|
||||
OPTION(BUILD_TESTS "jsoncons test suite" ON)
|
||||
|
||||
if(BUILD_TESTS)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
||||
# Installation
|
||||
# ============
|
||||
|
||||
include(GNUInstallDirs)
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
install(TARGETS jsoncons
|
||||
EXPORT ${PROJECT_NAME}-targets)
|
||||
|
||||
# Makes the project importable from the build directory
|
||||
export(EXPORT ${PROJECT_NAME}-targets
|
||||
FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake")
|
||||
|
||||
install(DIRECTORY ${JSONCONS_INCLUDE_DIR}/jsoncons
|
||||
${JSONCONS_INCLUDE_DIR}/jsoncons_ext
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
|
||||
# GNUInstallDirs "DATADIR" wrong here; CMake search path wants "share".
|
||||
set(JSONCONS_CMAKECONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" CACHE STRING "install path for jsonconsConfig.cmake")
|
||||
|
||||
configure_package_config_file(build_files/cmake/config.cmake.in
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
|
||||
INSTALL_DESTINATION ${JSONCONS_CMAKECONFIG_INSTALL_DIR})
|
||||
|
||||
# jsoncons is header-only and does not depend on the architecture.
|
||||
|
||||
write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
|
||||
VERSION ${${PROJECT_NAME}_VERSION}
|
||||
COMPATIBILITY AnyNewerVersion)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
|
||||
DESTINATION ${JSONCONS_CMAKECONFIG_INSTALL_DIR})
|
||||
install(EXPORT ${PROJECT_NAME}-targets
|
||||
FILE ${PROJECT_NAME}Targets.cmake
|
||||
DESTINATION ${JSONCONS_CMAKECONFIG_INSTALL_DIR})
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
// Copyright Daniel Parker 2013 - 2017.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
|
@ -1,951 +0,0 @@
|
|||
# JSONCONS
|
||||
|
||||
jsoncons is a C++, header-only library for constructing [JSON](http://www.json.org) and JSON-like
|
||||
data formats such as [CBOR](http://cbor.io/). It supports
|
||||
|
||||
- Parsing JSON-like text or binary formats into a tree model
|
||||
that defines an interface for accessing and modifying that data.
|
||||
|
||||
- Serializing the tree model into different JSON-like text or binary formats.
|
||||
|
||||
- Converting from JSON-like text or binary formats to C++ data structures and back via [json_type_traits](https://github.com/danielaparker/jsoncons/blob/master/doc/ref/json_type_traits.md).
|
||||
|
||||
- Streaming JSON read and write events, somewhat analogously to SAX (push parsing) and StAX (pull parsing) in the XML world.
|
||||
|
||||
Compared to other JSON libraries, jsoncons has been designed to handle very large JSON texts. At its heart are
|
||||
SAX style parsers and serializers. Its [json parser](https://github.com/danielaparker/jsoncons/blob/master/doc/ref/json_parser.md) is an
|
||||
incremental parser that can be fed its input in chunks, and does not require an entire file to be loaded in memory at one time.
|
||||
Its tree model is more compact than most, and can be made more compact still with a user-supplied
|
||||
allocator. It also supports memory efficient parsing of very large JSON texts with a [pull parser](https://github.com/danielaparker/jsoncons/blob/master/doc/ref/json_cursor.md),
|
||||
built on top of its incremental parser.
|
||||
|
||||
The [jsoncons data model](doc/ref/data-model.md) supports the familiar JSON types - nulls,
|
||||
booleans, numbers, strings, arrays, objects - plus byte strings. In addition, jsoncons
|
||||
supports semantic tagging of date-time values, timestamp values, big integers,
|
||||
big decimals, bigfloats and binary encodings. This allows it to preserve these type semantics when parsing
|
||||
JSON-like data formats such as CBOR that have them.
|
||||
|
||||
jsoncons is distributed under the [Boost Software License](http://www.boost.org/users/license.html).
|
||||
|
||||
## Extensions
|
||||
|
||||
- [jsonpointer](doc/ref/jsonpointer/jsonpointer.md) implements the IETF standard [JavaScript Object Notation (JSON) Pointer](https://tools.ietf.org/html/rfc6901)
|
||||
- [jsonpatch](doc/ref/jsonpatch/jsonpatch.md) implements the IETF standard [JavaScript Object Notation (JSON) Patch](https://tools.ietf.org/html/rfc6902)
|
||||
- [jsonpath](doc/ref/jsonpath/jsonpath.md) implements [Stefan Goessner's JSONPath](http://goessner.net/articles/JsonPath/). It also supports search and replace using JSONPath expressions.
|
||||
- [cbor](doc/ref/cbor/cbor.md) implements decode from and encode to the IETF standard [Concise Binary Object Representation](http://cbor.io/) data format.
|
||||
- [msgpack](doc/ref/msgpack/msgpack.md) implements decode from and encode to the [MessagePack](http://msgpack.org/index.html) data format.
|
||||
- [ubjson](doc/ref/ubjson/ubjson.md) implements decode from and encode to the [Universal Binary JSON Specification](http://ubjson.org/) data format.
|
||||
- [bson](doc/ref/bson/bson.md) implements decode from and encode to the [Binary JSON](http://bsonspec.org/) data format.
|
||||
- [csv](doc/ref/csv/csv.md) implements reading (writing) JSON values from (to) CSV files
|
||||
|
||||
## What users say
|
||||
|
||||
_"I am so happy I have come across your json c++ library!"_
|
||||
|
||||
_"I’m using your library for an external interface to pass data, as well as using the conversions from csv to json, which are really helpful for converting data for use in javascript ... it's a great library."_
|
||||
|
||||
_"this software is great and the ability to have an xpath like facility is so useful."_
|
||||
|
||||
_"really good"_ _"awesome project"_ _"very solid and very dependable"_ _"great job"_ _"Your repo rocks!!!!!"_
|
||||
|
||||
## Supported compilers
|
||||
|
||||
jsoncons uses some features that are new to C++ 11, including [move semantics](http://thbecker.net/articles/rvalue_references/section_02.html) and the [AllocatorAwareContainer](http://en.cppreference.com/w/cpp/concept/AllocatorAwareContainer) concept. It is tested in continuous integration on [AppVeyor](https://ci.appveyor.com/project/danielaparker/jsoncons), [Travis](https://travis-ci.org/danielaparker/jsoncons), and [doozer](https://doozer.io/).
|
||||
|
||||
| Compiler | Version |Architecture | Operating System | Notes |
|
||||
|-------------------------|---------------------------|-------------|-------------------|-------|
|
||||
| Microsoft Visual Studio | vs2015 (MSVC 19.0.24241.7)| x86,x64 | Windows 10 | |
|
||||
| | vs2017 | x86,x64 | Windows 10 | |
|
||||
| g++ | 4.8 and above | x64 | Ubuntu |`std::regex` isn't fully implemented in 4.8, so `jsoncons::jsonpath` regular expression filters aren't supported in 4.8 |
|
||||
| | 4.8.5 | x64 | CentOS 7.6 |`std::regex` isn't fully implemented in 4.8, so `jsoncons::jsonpath` regular expression filters aren't supported in 4.8 |
|
||||
| | 6.3.1 (Red Hat 6.3.1-1) | x64 | Fedora release 24 | |
|
||||
| clang | 3.8 and above | x64 | Ubuntu | |
|
||||
| clang xcode | 6.4 and above | x64 | OSX | |
|
||||
|
||||
It is also cross compiled for ARMv8-A architecture on Travis using clang and executed using the emulator qemu.
|
||||
|
||||
[UndefinedBehaviorSanitizer (UBSan)](http://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html) diagnostics are enabled for selected gcc and clang builds.
|
||||
|
||||
## Get jsoncons
|
||||
|
||||
Download the [latest release](https://github.com/danielaparker/jsoncons/releases) and unpack the zip file. Copy the directory `include/jsoncons` to your `include` directory. If you wish to use extensions, copy `include/jsoncons_ext` as well.
|
||||
|
||||
Or, download the latest code on [master](https://github.com/danielaparker/jsoncons/archive/master.zip).
|
||||
|
||||
## How to use it
|
||||
|
||||
- [Quick guide](http://danielaparker.github.io/jsoncons)
|
||||
- [Examples](doc/Examples.md)
|
||||
- [Reference](doc/Home.md)
|
||||
|
||||
As the `jsoncons` library has evolved, names have sometimes changed. To ease transition, jsoncons deprecates the old names but continues to support many of them. See the [deprecated list](doc/ref/deprecated.md) for the status of old names. The deprecated names can be suppressed by defining macro `JSONCONS_NO_DEPRECATED`, which is recommended for new code.
|
||||
|
||||
## Benchmarks
|
||||
|
||||
[json_benchmarks](https://github.com/danielaparker/json_benchmarks) provides some measurements about how `jsoncons` compares to other `json` libraries.
|
||||
|
||||
- [JSONTestSuite and JSON_checker test suites](https://danielaparker.github.io/json_benchmarks/)
|
||||
|
||||
- [Performance benchmarks with text and integers](https://github.com/danielaparker/json_benchmarks/blob/master/report/performance.md)
|
||||
|
||||
- [Performance benchmarks with text and doubles](https://github.com/danielaparker/json_benchmarks/blob/master/report/performance_fp.md)
|
||||
|
||||
### A simple example
|
||||
|
||||
```c++
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <jsoncons/json.hpp>
|
||||
|
||||
// For convenience
|
||||
using jsoncons::json;
|
||||
|
||||
int main()
|
||||
{
|
||||
json color_spaces = json::array();
|
||||
color_spaces.push_back("sRGB");
|
||||
color_spaces.push_back("AdobeRGB");
|
||||
color_spaces.push_back("ProPhoto RGB");
|
||||
|
||||
json image_sizing; // empty object
|
||||
image_sizing["Resize To Fit"] = true; // a boolean
|
||||
image_sizing["Resize Unit"] = "pixels"; // a string
|
||||
image_sizing["Resize What"] = "long_edge"; // a string
|
||||
image_sizing["Dimension 1"] = 9.84; // a double
|
||||
|
||||
json export_settings;
|
||||
|
||||
// create "File Format Options" as an object and put "Color Spaces" in it
|
||||
export_settings["File Format Options"]["Color Spaces"] = std::move(color_spaces);
|
||||
|
||||
export_settings["Image Sizing"] = std::move(image_sizing);
|
||||
|
||||
// Write to stream
|
||||
std::ofstream os("export_settings.json");
|
||||
os << export_settings;
|
||||
|
||||
// Read from stream
|
||||
std::ifstream is("export_settings.json");
|
||||
json j = json::parse(is);
|
||||
|
||||
// Pretty print
|
||||
std::cout << "(1)\n" << pretty_print(j) << "\n\n";
|
||||
|
||||
// Does object member exist?
|
||||
std::cout << "(2) " << std::boolalpha << j.contains("Image Sizing") << "\n\n";
|
||||
|
||||
// Get reference to object member
|
||||
const json& val = j["Image Sizing"];
|
||||
|
||||
// Access member as double
|
||||
std::cout << "(3) " << "Dimension 1 = " << val["Dimension 1"].as<double>() << "\n\n";
|
||||
|
||||
// Try access member with default
|
||||
std::cout << "(4) " << "Dimension 2 = " << val.get_with_default("Dimension 2",0.0) << "\n";
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```json
|
||||
(1)
|
||||
{
|
||||
"File Format Options": {
|
||||
"Color Spaces": ["sRGB","AdobeRGB","ProPhoto RGB"],
|
||||
"Image Formats": ["JPEG","PSD","TIFF","DNG"]
|
||||
},
|
||||
"File Settings": {
|
||||
"Color Space": "sRGB",
|
||||
"Image Format": "JPEG",
|
||||
"Limit File Size": true,
|
||||
"Limit File Size To": 10000
|
||||
},
|
||||
"Image Sizing": {
|
||||
"Dimension 1": 9.84,
|
||||
"Resize To Fit": true,
|
||||
"Resize Unit": "pixels",
|
||||
"Resize What": "long_edge"
|
||||
}
|
||||
}
|
||||
|
||||
(2) true
|
||||
|
||||
(3) Dimension 1 = 9.8
|
||||
|
||||
(4) Dimension 2 = 0
|
||||
```
|
||||
|
||||
## About jsoncons::basic_json
|
||||
|
||||
The jsoncons library provides a `basic_json` class template, which is the generalization of a `json` value for different
|
||||
character types, different policies for ordering name-value pairs, etc. A `basic_json` provides a tree model
|
||||
of JSON-like data formats, and defines an interface for accessing and modifying that data.
|
||||
Despite its name, it is not JSON specific.
|
||||
|
||||
```c++
|
||||
typedef basic_json<char,
|
||||
ImplementationPolicy = sorted_policy,
|
||||
Allocator = std::allocator<char>> json;
|
||||
```
|
||||
The library includes four instantiations of `basic_json`:
|
||||
|
||||
- [json](doc/ref/json.md) constructs a utf8 character json value that sorts name-value members alphabetically
|
||||
|
||||
- [ojson](doc/ref/ojson.md) constructs a utf8 character json value that preserves the original name-value insertion order
|
||||
|
||||
- [wjson](doc/ref/wjson.md) constructs a wide character json value that sorts name-value members alphabetically
|
||||
|
||||
- [wojson](doc/ref/wojson.md) constructs a wide character json value that preserves the original name-value insertion order
|
||||
|
||||
## More examples
|
||||
|
||||
[Encode C++ data structures to JSON, decode JSON to C++ data structures](#E1)
|
||||
|
||||
[Playing around with CBOR, JSON, and CSV](#E2)
|
||||
|
||||
[Query CBOR with JSONPath](#E3)
|
||||
|
||||
[Pull parser example](#E4)
|
||||
|
||||
[Iterate over a json stream with staj iterators](#E5)
|
||||
|
||||
[Dump json content into a larger document](#E6)
|
||||
|
||||
<div id="E1"/>
|
||||
|
||||
### Encode C++ data structures to JSON, decode JSON to C++ data structures
|
||||
|
||||
jsoncons supports conversion between C++ data structures and JSON. The functions [encode_json](doc/ref/encode_json.md)
|
||||
and [decode_json](doc/ref/decode_json.md) convert C++ data structures to JSON formatted strings or streams and back.
|
||||
Encode and decode work for all C++ classes that have
|
||||
[json_type_traits](https://github.com/danielaparker/jsoncons/blob/master/doc/ref/json_type_traits.md)
|
||||
defined. The standard library containers are already supported, and you can specialize `json_type_traits`
|
||||
for your own types in the `jsoncons` namespace.
|
||||
|
||||
`JSONCONS_MEMBER_TRAITS_DECL` is a macro that simplifies the creation of the necessary boilerplate
|
||||
from member data. It must be placed outside any namespace blocks.
|
||||
|
||||
```c++
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <jsoncons/json.hpp>
|
||||
|
||||
namespace ns {
|
||||
|
||||
struct reputon
|
||||
{
|
||||
std::string rater;
|
||||
std::string assertion;
|
||||
std::string rated;
|
||||
double rating;
|
||||
|
||||
friend bool operator==(const reputon& lhs, const reputon& rhs)
|
||||
{
|
||||
return lhs.rater == rhs.rater && lhs.assertion == rhs.assertion &&
|
||||
lhs.rated == rhs.rated && lhs.rating == rhs.rating;
|
||||
}
|
||||
|
||||
friend bool operator!=(const reputon& lhs, const reputon& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
};
|
||||
};
|
||||
|
||||
class reputation_object
|
||||
{
|
||||
std::string application;
|
||||
std::vector<reputon> reputons;
|
||||
|
||||
// Make json_type_traits specializations friends to give accesses to private members
|
||||
JSONCONS_TYPE_TRAITS_FRIEND;
|
||||
public:
|
||||
reputation_object()
|
||||
{
|
||||
}
|
||||
reputation_object(const std::string& application, const std::vector<reputon>& reputons)
|
||||
: application(application), reputons(reputons)
|
||||
{}
|
||||
|
||||
friend bool operator==(const reputation_object& lhs, const reputation_object& rhs)
|
||||
{
|
||||
return (lhs.application == rhs.application) && (lhs.reputons == rhs.reputons);
|
||||
}
|
||||
|
||||
friend bool operator!=(const reputation_object& lhs, const reputation_object& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
} // namespace ns
|
||||
|
||||
// Declare the traits. Specify which data members need to be serialized.
|
||||
JSONCONS_MEMBER_TRAITS_DECL(ns::reputon, rater, assertion, rated, rating)
|
||||
JSONCONS_MEMBER_TRAITS_DECL(ns::reputation_object, application, reputons)
|
||||
|
||||
using namespace jsoncons; // for convenience
|
||||
|
||||
int main()
|
||||
{
|
||||
ns::reputation_object val("hiking", { ns::reputon{"HikingAsylum.example.com","strong-hiker","Marilyn C",0.90} });
|
||||
|
||||
std::string s;
|
||||
encode_json(val, s, indenting::indent);
|
||||
std::cout << s << "\n";
|
||||
|
||||
auto val2 = decode_json<ns::reputation_object>(s);
|
||||
|
||||
assert(val2 == val);
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```
|
||||
{
|
||||
"application": "hiking",
|
||||
"reputons": [
|
||||
{
|
||||
"assertion": "strong-hiker",
|
||||
"rated": "Marilyn C",
|
||||
"rater": "HikingAsylum.example.com",
|
||||
"rating": 0.9
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
See [examples](https://github.com/danielaparker/jsoncons/blob/master/doc/Examples.md#G1)
|
||||
|
||||
<div id="E2"/>
|
||||
|
||||
### Playing around with CBOR, JSON, and CSV
|
||||
|
||||
```c++
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons_ext/cbor/cbor.hpp>
|
||||
#include <jsoncons_ext/jsonpointer/jsonpointer.hpp>
|
||||
#include <jsoncons_ext/csv/csv.hpp>
|
||||
|
||||
// For convenience
|
||||
using namespace jsoncons;
|
||||
|
||||
int main()
|
||||
{
|
||||
// Construct some CBOR using the streaming API
|
||||
std::vector<uint8_t> b;
|
||||
cbor::cbor_bytes_encoder encoder(b);
|
||||
encoder.begin_array(); // indefinite length outer array
|
||||
encoder.begin_array(3); // a fixed length array
|
||||
encoder.string_value("foo");
|
||||
encoder.byte_string_value(byte_string{'P','u','s','s'}); // no suggested conversion
|
||||
encoder.string_value("-18446744073709551617", semantic_tag::bigint);
|
||||
encoder.end_array();
|
||||
encoder.end_array();
|
||||
encoder.flush();
|
||||
|
||||
// Print bytes
|
||||
std::cout << "(1) ";
|
||||
for (auto c : b)
|
||||
{
|
||||
std::cout << std::hex << std::setprecision(2) << std::setw(2)
|
||||
<< std::setfill('0') << static_cast<int>(c);
|
||||
}
|
||||
std::cout << "\n\n";
|
||||
/*
|
||||
9f -- Start indefinte length array
|
||||
83 -- Array of length 3
|
||||
63 -- String value of length 3
|
||||
666f6f -- "foo"
|
||||
44 -- Byte string value of length 4
|
||||
50757373 -- 'P''u''s''s'
|
||||
c3 -- Tag 3 (negative bignum)
|
||||
49 -- Byte string value of length 9
|
||||
010000000000000000 -- Bytes content
|
||||
ff -- "break"
|
||||
*/
|
||||
// Unpack bytes into a json variant value, and add some more elements
|
||||
json j = cbor::decode_cbor<json>(b);
|
||||
|
||||
// Loop over the rows
|
||||
std::cout << "(2)\n";
|
||||
for (const json& row : j.array_range())
|
||||
{
|
||||
std::cout << row << "\n";
|
||||
}
|
||||
std::cout << "\n";
|
||||
|
||||
// Get bignum value at position 0/2 using jsonpointer
|
||||
json& v = jsonpointer::get(j, "/0/2");
|
||||
std::cout << "(3) " << v.as<std::string>() << "\n\n";
|
||||
|
||||
// Print JSON representation with default options
|
||||
std::cout << "(4)\n";
|
||||
std::cout << pretty_print(j) << "\n\n";
|
||||
|
||||
// Print JSON representation with different options
|
||||
json_options options;
|
||||
options.byte_string_format(byte_string_chars_format::base64)
|
||||
.bigint_format(bigint_chars_format::base64url);
|
||||
std::cout << "(5)\n";
|
||||
std::cout << pretty_print(j, options) << "\n\n";
|
||||
|
||||
// Add some more elements
|
||||
|
||||
json another_array = json::array();
|
||||
another_array.emplace_back(byte_string({'P','u','s','s'}),
|
||||
semantic_tag::base64); // suggested conversion to base64
|
||||
another_array.emplace_back("273.15", semantic_tag::bigdec);
|
||||
another_array.emplace(another_array.array_range().begin(),"bar"); // place at front
|
||||
|
||||
j.push_back(std::move(another_array));
|
||||
std::cout << "(6)\n";
|
||||
std::cout << pretty_print(j) << "\n\n";
|
||||
|
||||
// Get big decimal value at position /1/2 using jsonpointer
|
||||
json& ref = jsonpointer::get(j, "/1/2");
|
||||
std::cout << "(7) " << ref.as<std::string>() << "\n\n";
|
||||
|
||||
#if (defined(__GNUC__) || defined(__clang__)) && (!defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128))
|
||||
// e.g. if code compiled with GCC and std=gnu++11 (rather than std=c++11)
|
||||
__int128 i = j[1][2].as<__int128>();
|
||||
#endif
|
||||
|
||||
// Get byte string value at position /1/1 as a byte_string
|
||||
byte_string bs = j[1][1].as<byte_string>();
|
||||
std::cout << "(8) " << bs << "\n\n";
|
||||
|
||||
// or alternatively as a std::vector<uint8_t>
|
||||
std::vector<uint8_t> u = j[1][1].as<std::vector<uint8_t>>();
|
||||
|
||||
// Repack bytes
|
||||
std::vector<uint8_t> b2;
|
||||
cbor::encode_cbor(j, b2);
|
||||
|
||||
// Print the repacked bytes
|
||||
std::cout << "(9) ";
|
||||
for (auto c : b2)
|
||||
{
|
||||
std::cout << std::hex << std::setprecision(2) << std::setw(2)
|
||||
<< std::setfill('0') << static_cast<int>(c);
|
||||
}
|
||||
std::cout << "\n\n";
|
||||
/*
|
||||
82 -- Array of length 2
|
||||
83 -- Array of length 3
|
||||
63 -- String value of length 3
|
||||
666f6f -- "foo"
|
||||
44 -- Byte string value of length 4
|
||||
50757373 -- 'P''u''s''s'
|
||||
c3 -- Tag 3 (negative bignum)
|
||||
49 -- Byte string value of length 9
|
||||
010000000000000000 -- Bytes content
|
||||
83 -- Another array of length 3
|
||||
63 -- String value of length 3
|
||||
626172 -- "bar"
|
||||
d6 - Expected conversion to base64
|
||||
44 -- Byte string value of length 4
|
||||
50757373 -- 'P''u''s''s'
|
||||
c4 -- Tag 4 (decimal fraction)
|
||||
82 -- Array of length 2
|
||||
21 -- -2
|
||||
19 6ab3 -- 27315
|
||||
*/
|
||||
// Encode to CSV
|
||||
csv::csv_options csv_options;
|
||||
csv_options.column_names("Column 1,Column 2,Column 3");
|
||||
|
||||
std::cout << "(10)\n";
|
||||
csv::encode_csv(j, std::cout, csv_options);
|
||||
}
|
||||
|
||||
```
|
||||
Output:
|
||||
```
|
||||
(1) 9f8363666f6f4450757373c349010000000000000000ff
|
||||
|
||||
(2)
|
||||
["foo","UHVzcw","-18446744073709551617"]
|
||||
|
||||
(3) -18446744073709551617
|
||||
|
||||
(4)
|
||||
[
|
||||
["foo", "UHVzcw", "-18446744073709551617"]
|
||||
]
|
||||
|
||||
(5)
|
||||
[
|
||||
["foo", "UHVzcw==", "~AQAAAAAAAAAA"]
|
||||
]
|
||||
|
||||
(6)
|
||||
[
|
||||
["foo", "UHVzcw", "-18446744073709551617"],
|
||||
["bar", "UHVzcw==", "273.15"]
|
||||
]
|
||||
|
||||
(7) 273.15
|
||||
|
||||
(8) 50757373
|
||||
|
||||
(9) 828363666f6f4450757373c3490100000000000000008363626172d64450757373c48221196ab3
|
||||
|
||||
(10)
|
||||
Column 1,Column 2,Column 3
|
||||
foo,UHVzcw,-18446744073709551617
|
||||
bar,UHVzcw==,273.15
|
||||
```
|
||||
|
||||
<div id="E3"/>
|
||||
|
||||
### Query CBOR with JSONPath
|
||||
```c++
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons_ext/cbor/cbor.hpp>
|
||||
#include <jsoncons_ext/jsonpath/json_query.hpp>
|
||||
#include <iomanip>
|
||||
|
||||
using namespace jsoncons; // For convenience
|
||||
|
||||
int main()
|
||||
{
|
||||
// Construct a json array of numbers
|
||||
json j = json::array();
|
||||
|
||||
j.emplace_back(5.0);
|
||||
|
||||
j.emplace_back(0.000071);
|
||||
|
||||
j.emplace_back("-18446744073709551617",semantic_tag::bigint);
|
||||
|
||||
j.emplace_back("1.23456789012345678901234567890", semantic_tag::bigdec);
|
||||
|
||||
j.emplace_back("0x3p-1", semantic_tag::bigfloat);
|
||||
|
||||
// Encode to JSON
|
||||
std::cout << "(1)\n";
|
||||
std::cout << pretty_print(j);
|
||||
std::cout << "\n\n";
|
||||
|
||||
// as<std::string>() and as<double>()
|
||||
std::cout << "(2)\n";
|
||||
std::cout << std::dec << std::setprecision(15);
|
||||
for (const auto& item : j.array_range())
|
||||
{
|
||||
std::cout << item.as<std::string>() << ", " << item.as<double>() << "\n";
|
||||
}
|
||||
std::cout << "\n";
|
||||
|
||||
// Encode to CBOR
|
||||
std::vector<uint8_t> v;
|
||||
cbor::encode_cbor(j,v);
|
||||
|
||||
std::cout << "(3)\n";
|
||||
for (auto c : v)
|
||||
{
|
||||
std::cout << std::hex << std::setprecision(2) << std::setw(2)
|
||||
<< std::setfill('0') << static_cast<int>(c);
|
||||
}
|
||||
std::cout << "\n\n";
|
||||
/*
|
||||
85 -- Array of length 5
|
||||
fa -- float
|
||||
40a00000 -- 5.0
|
||||
fb -- double
|
||||
3f129cbab649d389 -- 0.000071
|
||||
c3 -- Tag 3 (negative bignum)
|
||||
49 -- Byte string value of length 9
|
||||
010000000000000000
|
||||
c4 -- Tag 4 (decimal fraction)
|
||||
82 -- Array of length 2
|
||||
38 -- Negative integer of length 1
|
||||
1c -- -29
|
||||
c2 -- Tag 2 (positive bignum)
|
||||
4d -- Byte string value of length 13
|
||||
018ee90ff6c373e0ee4e3f0ad2
|
||||
c5 -- Tag 5 (bigfloat)
|
||||
82 -- Array of length 2
|
||||
20 -- -1
|
||||
03 -- 3
|
||||
*/
|
||||
|
||||
// Decode back to json
|
||||
json other = cbor::decode_cbor<json>(v);
|
||||
assert(other == j);
|
||||
|
||||
// Query with JSONPath
|
||||
std::cout << "(4)\n";
|
||||
json result = jsonpath::json_query(other,"$[?(@ < 1.5)]");
|
||||
std::cout << pretty_print(result) << "\n\n";
|
||||
```
|
||||
Output:
|
||||
```
|
||||
(1)
|
||||
[
|
||||
5.0,
|
||||
7.1e-05,
|
||||
"-18446744073709551617",
|
||||
"1.23456789012345678901234567890",
|
||||
[-1, 3]
|
||||
]
|
||||
|
||||
(2)
|
||||
5.0, 5
|
||||
7.1e-05, 7.1e-05
|
||||
-18446744073709551617, -1.84467440737096e+19
|
||||
1.23456789012345678901234567890, 1.23456789012346
|
||||
1.5, 1.5
|
||||
|
||||
(3)
|
||||
85fa40a00000fb3f129cbab649d389c349010000000000000000c482381cc24d018ee90ff6c373e0ee4e3f0ad2c5822003
|
||||
|
||||
(4)
|
||||
[
|
||||
7.1e-05,
|
||||
"-18446744073709551617",
|
||||
"1.23456789012345678901234567890"
|
||||
]
|
||||
```
|
||||
|
||||
<div id="E4"/>
|
||||
|
||||
### Pull parser example
|
||||
|
||||
A typical pull parsing application will repeatedly process the `current()`
|
||||
event and call `next()` to advance to the next event, until `done()`
|
||||
returns `true`.
|
||||
|
||||
The example JSON text, `book_catalog.json`, is used by the examples below.
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"author" : "Haruki Murakami",
|
||||
"title" : "Hard-Boiled Wonderland and the End of the World",
|
||||
"isbn" : "0679743464",
|
||||
"publisher" : "Vintage",
|
||||
"date" : "1993-03-02",
|
||||
"price": 18.90
|
||||
},
|
||||
{
|
||||
"author" : "Graham Greene",
|
||||
"title" : "The Comedians",
|
||||
"isbn" : "0099478374",
|
||||
"publisher" : "Vintage Classics",
|
||||
"date" : "2005-09-21",
|
||||
"price": 15.74
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
#### Reading the JSON stream
|
||||
```c++
|
||||
std::ifstream is("book_catalog.json");
|
||||
|
||||
json_cursor reader(is);
|
||||
|
||||
for (; !reader.done(); reader.next())
|
||||
{
|
||||
const auto& event = reader.current();
|
||||
switch (event.event_type())
|
||||
{
|
||||
case staj_event_type::begin_array:
|
||||
std::cout << "begin_array\n";
|
||||
break;
|
||||
case staj_event_type::end_array:
|
||||
std::cout << "end_array\n";
|
||||
break;
|
||||
case staj_event_type::begin_object:
|
||||
std::cout << "begin_object\n";
|
||||
break;
|
||||
case staj_event_type::end_object:
|
||||
std::cout << "end_object\n";
|
||||
break;
|
||||
case staj_event_type::name:
|
||||
// If underlying type is string, can return as string_view
|
||||
std::cout << "name: " << event.as<jsoncons::string_view>() << "\n";
|
||||
break;
|
||||
case staj_event_type::string_value:
|
||||
std::cout << "string_value: " << event.as<jsoncons::string_view>() << "\n";
|
||||
break;
|
||||
case staj_event_type::null_value:
|
||||
std::cout << "null_value: " << event.as<std::string>() << "\n";
|
||||
break;
|
||||
case staj_event_type::bool_value:
|
||||
std::cout << "bool_value: " << event.as<std::string>() << "\n";
|
||||
break;
|
||||
case staj_event_type::int64_value:
|
||||
std::cout << "int64_value: " << event.as<std::string>() << "\n";
|
||||
break;
|
||||
case staj_event_type::uint64_value:
|
||||
std::cout << "uint64_value: " << event.as<std::string>() << "\n";
|
||||
break;
|
||||
case staj_event_type::double_value:
|
||||
// Return as string, could also use event.as<double>()
|
||||
std::cout << "double_value: " << event.as<std::string>() << "\n";
|
||||
break;
|
||||
default:
|
||||
std::cout << "Unhandled event type\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```
|
||||
begin_array
|
||||
begin_object
|
||||
name: author
|
||||
string_value: Haruki Murakami
|
||||
name: title
|
||||
string_value: Hard-Boiled Wonderland and the End of the World
|
||||
name: isbn
|
||||
string_value: 0679743464
|
||||
name: publisher
|
||||
string_value: Vintage
|
||||
name: date
|
||||
string_value: 1993-03-02
|
||||
name: price
|
||||
double_value: 18.90
|
||||
end_object
|
||||
begin_object
|
||||
name: author
|
||||
string_value: Graham Greene
|
||||
name: title
|
||||
string_value: The Comedians
|
||||
name: isbn
|
||||
string_value: 0099478374
|
||||
name: publisher
|
||||
string_value: Vintage Classics
|
||||
name: date
|
||||
string_value: 2005-09-21
|
||||
name: price
|
||||
double_value: 15.74
|
||||
end_object
|
||||
end_array
|
||||
```
|
||||
|
||||
<div id="E5"/>
|
||||
|
||||
#### Implementing a staj_filter
|
||||
|
||||
```c++
|
||||
// A stream filter to filter out all events except name
|
||||
// and restrict name to "author"
|
||||
|
||||
class author_filter : public staj_filter
|
||||
{
|
||||
bool accept_next_ = false;
|
||||
public:
|
||||
bool accept(const staj_event& event, const ser_context&) override
|
||||
{
|
||||
if (event.event_type() == staj_event_type::name &&
|
||||
event.as<jsoncons::string_view>() == "author")
|
||||
{
|
||||
accept_next_ = true;
|
||||
return false;
|
||||
}
|
||||
else if (accept_next_)
|
||||
{
|
||||
accept_next_ = false;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
accept_next_ = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
#### Filtering the JSON stream
|
||||
|
||||
```c++
|
||||
std::ifstream is("book_catalog.json");
|
||||
|
||||
author_filter filter;
|
||||
json_cursor reader(is, filter);
|
||||
|
||||
for (; !reader.done(); reader.next())
|
||||
{
|
||||
const auto& event = reader.current();
|
||||
switch (event.event_type())
|
||||
{
|
||||
case staj_event_type::string_value:
|
||||
std::cout << event.as<jsoncons::string_view>() << "\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```
|
||||
Haruki Murakami
|
||||
Graham Greene
|
||||
```
|
||||
|
||||
See [json_cursor](doc/ref/json_cursor.md)
|
||||
|
||||
### Iterate over a json stream with staj iterators
|
||||
|
||||
```c++
|
||||
const std::string example = R"(
|
||||
[
|
||||
{
|
||||
"employeeNo" : "101",
|
||||
"name" : "Tommy Cochrane",
|
||||
"title" : "Supervisor"
|
||||
},
|
||||
{
|
||||
"employeeNo" : "102",
|
||||
"name" : "Bill Skeleton",
|
||||
"title" : "Line manager"
|
||||
}
|
||||
]
|
||||
)";
|
||||
|
||||
int main()
|
||||
{
|
||||
std::istringstream is(example);
|
||||
|
||||
json_cursor reader(is);
|
||||
|
||||
staj_array_iterator<json> it(reader);
|
||||
|
||||
for (const auto& j : it)
|
||||
{
|
||||
std::cout << pretty_print(j) << "\n";
|
||||
}
|
||||
std::cout << "\n\n";
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```
|
||||
{
|
||||
"employeeNo": "101",
|
||||
"name": "Tommy Cochrane",
|
||||
"title": "Supervisor"
|
||||
}
|
||||
{
|
||||
"employeeNo": "102",
|
||||
"name": "Bill Skeleton",
|
||||
"title": "Line manager"
|
||||
}
|
||||
```
|
||||
See [staj_array_iterator](doc/ref/staj_array_iterator.md) and [staj_object_iterator](doc/ref/staj_object_iterator.md)
|
||||
|
||||
<div id="E6"/>
|
||||
|
||||
### Dump json content into a larger document
|
||||
|
||||
```c++
|
||||
#include <jsoncons/json.hpp>
|
||||
|
||||
using namespace jsoncons;
|
||||
|
||||
int main()
|
||||
{
|
||||
const json some_books = json::parse(R"(
|
||||
[
|
||||
{
|
||||
"title" : "Kafka on the Shore",
|
||||
"author" : "Haruki Murakami",
|
||||
"price" : 25.17
|
||||
},
|
||||
{
|
||||
"title" : "Women: A Novel",
|
||||
"author" : "Charles Bukowski",
|
||||
"price" : 12.00
|
||||
}
|
||||
]
|
||||
)");
|
||||
|
||||
const json more_books = json::parse(R"(
|
||||
[
|
||||
{
|
||||
"title" : "A Wild Sheep Chase: A Novel",
|
||||
"author" : "Haruki Murakami",
|
||||
"price" : 9.01
|
||||
},
|
||||
{
|
||||
"title" : "Cutter's Way",
|
||||
"author" : "Ivan Passer",
|
||||
"price" : 8.00
|
||||
}
|
||||
]
|
||||
)");
|
||||
|
||||
json_encoder encoder(std::cout, jsoncons::indenting::indent); // pretty print
|
||||
serializer.begin_array();
|
||||
for (const auto& book : some_books.array_range())
|
||||
{
|
||||
book.dump(encoder);
|
||||
}
|
||||
for (const auto& book : more_books.array_range())
|
||||
{
|
||||
book.dump(encoder);
|
||||
}
|
||||
serializer.end_array();
|
||||
serializer.flush();
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```json
|
||||
[
|
||||
{
|
||||
"author": "Haruki Murakami",
|
||||
"price": 25.17,
|
||||
"title": "Kafka on the Shore"
|
||||
},
|
||||
{
|
||||
"author": "Charles Bukowski",
|
||||
"price": 12.0,
|
||||
"title": "Women: A Novel"
|
||||
},
|
||||
{
|
||||
"author": "Haruki Murakami",
|
||||
"price": 9.01,
|
||||
"title": "A Wild Sheep Chase: A Novel"
|
||||
},
|
||||
{
|
||||
"author": "Ivan Passer",
|
||||
"price": 8.0,
|
||||
"title": "Cutter's Way"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Building the test suite and examples with CMake
|
||||
|
||||
[CMake](https://cmake.org/) is a cross-platform build tool that generates makefiles and solutions for the compiler environment of your choice. On Windows you can download a [Windows Installer package](https://cmake.org/download/). On Linux it is usually available as a package, e.g., on Ubuntu,
|
||||
```
|
||||
sudo apt-get install cmake
|
||||
```
|
||||
Once cmake is installed, you can build the tests:
|
||||
```
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ../ -DBUILD_TESTS=ON
|
||||
cmake --build . --target test_jsoncons --config Release
|
||||
```
|
||||
Run from the jsoncons tests directory:
|
||||
|
||||
On Windows:
|
||||
```
|
||||
..\build\tests\Release\test_jsoncons
|
||||
```
|
||||
|
||||
On UNIX:
|
||||
```
|
||||
../build/tests/Release/test_jsoncons
|
||||
```
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
The jsoncons platform dependent binary configuration draws on to the excellent MIT licensed [tinycbor](https://github.com/intel/tinycbor).
|
||||
|
||||
A big thanks to Milo Yip, author of [RapidJSON](http://rapidjson.org/), for raising the quality of JSON libraries across the board, by publishing [the benchmarks](https://github.com/miloyip/nativejson-benchmark), and contacting this project (among others) to share the results.
|
||||
|
||||
The jsoncons implementation of the Grisu3 algorithm for printing floating-point numbers follows Florian Loitsch's MIT licensed [grisu3_59_56 implementation](http://florian.loitsch.com/publications), with minor modifications.
|
||||
|
||||
The macro `JSONCONS_MEMBER_TRAITS_DECL` was inspired by Martin York's [ThorsSerializer](https://github.com/Loki-Astari/ThorsSerializer)
|
||||
|
||||
Special thanks to our [contributors](https://github.com/danielaparker/jsoncons/blob/master/acknowledgements.md)
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
# Roadmap
|
||||
|
||||
### For later releases
|
||||
|
||||
- Generaliztion and enhancement of encode and decode functions
|
||||
|
||||
At this point we'll slap a Version 1.0.0 Full Release stamp on `jsoncons`
|
||||
(we've been leading up to this since 2013.)
|
||||
|
||||
### Post 1.0.0
|
||||
|
||||
- Support more error recovery and introduce optional `lenient_error_handler`.
|
||||
|
||||
- Implement [Concise data definition language (CDDL)](https://tools.ietf.org/html/draft-ietf-cbor-cddl-08) for schema validation in `jsoncons_ext`
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
A big thanks to the following individuals for contributing:
|
||||
|
||||
- Andrew Hutko (early code review)
|
||||
|
||||
- [Marc Chevrier](https://github.com/MarkaPola) (contributed clang port, build files, json is<T> and as<T> methods,
|
||||
and make_array template implementation.)
|
||||
|
||||
- [Pedro Larroy](https://github.com/larroy) and the developers of the clearskies_core project (contributed build
|
||||
system for posix systems, adding GCC to list of supported compilers, bug fixes,
|
||||
Android fix)
|
||||
|
||||
- [Cory Fields](https://github.com/theuni) for fixing warnings about unused variables
|
||||
|
||||
- [Vitaliy Gusev](https://github.com/gusev-vitaliy) (reported error in json object operator[size_t i])
|
||||
|
||||
- [Alex Merry](https://github.com/amerry) for reporting errors with "typename" keyword experienced with gcc and providing
|
||||
workaround for gcc 4.8 regex issues.
|
||||
|
||||
- [Ignatov Serguei](https://github.com/sergign60) (reported issues experienced with gcc for 0.95 and
|
||||
0.96 candidate and helped fix them)
|
||||
|
||||
- [Milan Burda](https://github.com/miniak) for fix for clang build error
|
||||
|
||||
- [Peter Tissen](https://github.com/Bigpet), for reporting and suggesting a fix for get(name,default_val)
|
||||
|
||||
- [Tom Bass](https://github.com/tbass) for assistance with clang build errors
|
||||
|
||||
- [Andrey Alifanov](https://github.com/AndreyAlifanov) and [Amit Naik](https://github.com/amitnaik1) for failing test cases for JSON Path
|
||||
|
||||
- [Yuri Plaksyuk](https://github.com/yplaksyuk) for contributing an extension to JsonPath to allow filter
|
||||
expressions over a single object.
|
||||
|
||||
- [Nikolay Amiantov](https://github.com/abbradar) for fixing compilation errors and warnings by GCC and
|
||||
Clang, adding read support for std::array and, most appreciated,
|
||||
adding Travis CI configuration.
|
||||
|
||||
- [jakalx](https://github.com/jakalx) contributed fix for operator== throws when comparing a string
|
||||
against an empty object
|
||||
|
||||
- [Alexander](https://github.com/rog13) for contributing fix to jsonpatch::diff
|
||||
|
||||
- [Stefano Sinigardi](https://github.com/cenit) for contributing workaround for vs2017 platform issue
|
||||
|
||||
- [xezon](https://github.com/danielaparker/jsoncons/pull/140) for proposing decode_csv and encode_csv functions, the
|
||||
ignore_empty_lines option, and fixes to mismatched allocator types. Also for fixes and improvements in string_view code.
|
||||
|
||||
- Vojtech Fried for contributing patches to JSONCONS_DEFINE_LITERAL
|
||||
and to json::as_string to remove warnings
|
||||
|
||||
- [Joshua Pritikin](https://github.com/jpritikin), for reporting gcc ubsan runtime warnings about
|
||||
load of misaligned addresses, and verifying fix
|
||||
|
||||
- [Tobias Hermann](https://github.com/Dobiasd), for reporting issue with `UINT_MAX` not declared
|
||||
in `bignum.hpp`, and proposing fix.
|
||||
|
||||
- [Cebtenzzre](https://github.com/Cebtenzzre), for finding and fixing an issue with conversions on
|
||||
a basic_json value leading to an infinite recursion when the
|
||||
value is a bignum, and for fixing undefined behavior in the bignum
|
||||
class.
|
||||
|
||||
- [massimo morara](https://github.com/massimomorara) for reporting numerous issues
|
||||
|
||||
- [Alexander B](https://github.com/bas524), for uncovering a bug in how json_parser validated
|
||||
UTF-8 strings.
|
||||
|
||||
- [zhskyy](https://github.com/zhskyy), for contributing __FILE__ and __LINE__ macros removed
|
||||
from JSONCONS_ASSERT if not defined _DEBUG.
|
||||
|
||||
- [soberich](https://github.com/soberich), for contributing the jsonpath sum and prod functions,
|
||||
and a proposal for aggregation functions that work outside a filter.
|
||||
|
||||
- [patternoia](https://github.com/patternoia) for fixing the installation script
|
||||
to include copying the jsoncons_ext directory into the installation place
|
||||
|
||||
- [mikewallis](https://github.com/mikewallis) for removing redundant macro continuation character in JSONCONS_TYPE_TRAITS_DECL
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
build: false
|
||||
|
||||
environment:
|
||||
vsversion: none
|
||||
arch: default
|
||||
matrix:
|
||||
- platform: vs
|
||||
vsversion: 2015
|
||||
arch: x86
|
||||
FLAGS: ""
|
||||
|
||||
- platform: vs
|
||||
vsversion: 2015
|
||||
arch: x86
|
||||
FLAGS: ""
|
||||
|
||||
- platform: vs
|
||||
vsversion: 2015
|
||||
arch: x86
|
||||
FLAGS: "/permissive- /std:c++latest /utf-8"
|
||||
|
||||
- platform: vs
|
||||
vsversion: 2015
|
||||
arch: x64
|
||||
FLAGS: ""
|
||||
|
||||
- platform: vs
|
||||
vsversion: 2017
|
||||
arch: x64
|
||||
FLAGS: ""
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
|
||||
- platform: vs
|
||||
vsversion: 2017
|
||||
arch: x64
|
||||
FLAGS: "/permissive- /std:c++latest /utf-8"
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
|
||||
- platform: vs
|
||||
vsversion: 2017
|
||||
arch: ARM
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
|
||||
init:
|
||||
- git config --global core.autocrlf input
|
||||
|
||||
before_build:
|
||||
# Remove the following from the path, as it will interfere with
|
||||
# the MinGW builds
|
||||
- set PATH=%PATH:C:\Program Files\Git\usr\bin;=%
|
||||
- if %platform%==msvc call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat"
|
||||
- if %platform%==msvc cmake -G "NMake Makefiles" -DCMAKE_INSTALL_PREFIX=%P%
|
||||
- if %platform%==vs (
|
||||
set "makecommand=Visual Studio"
|
||||
)
|
||||
- set "vcx=false"
|
||||
- set "vcs=false"
|
||||
- if %platform%==vs (
|
||||
set "vcx=true"
|
||||
)
|
||||
- if %vsversion%==2015 (
|
||||
set "makecommand=%makecommand% 14 %vsversion%"
|
||||
)
|
||||
- if %vsversion%==2017 (
|
||||
set "makecommand=%makecommand% 15 %vsversion%"
|
||||
)
|
||||
- if %arch%==x64 (
|
||||
set "makecommand=%makecommand% Win64"
|
||||
)
|
||||
- if %arch%==ARM (
|
||||
set "makecommand=%makecommand% ARM"
|
||||
)
|
||||
|
||||
- cmake -G "%makecommand%" -D BUILD_TESTS=1 .
|
||||
|
||||
build_script:
|
||||
- cmake --build . --target test_jsoncons --config Release
|
||||
- cd tests
|
||||
|
||||
test_script:
|
||||
- set "testplatform=%platform%"
|
||||
# Can not run ARM builds on x86/x64 build images
|
||||
- if %arch%==ARM (
|
||||
set "testplatform=none"
|
||||
)
|
||||
- if %testplatform%==vs .\Release\test_jsoncons
|
|
@ -1,5 +0,0 @@
|
|||
#!/bin/bash -x
|
||||
|
||||
INSTALL_PREFIX=$(pwd)/../build
|
||||
|
||||
cp -rf include/* ${INSTALL_PREFIX}/include
|
|
@ -1,7 +0,0 @@
|
|||
#
|
||||
# Global Configuration for MacOS platform
|
||||
#
|
||||
|
||||
# customize compiler flags
|
||||
## Add new flags
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
#
|
||||
# Global Configuration for linux platform
|
||||
#
|
||||
|
||||
#
|
||||
# GNU libstdc++ runtime is not supported because not yet C++11 compliant
|
||||
#
|
||||
|
||||
# customize compiler flags
|
||||
## Add new flags
|
||||
add_definitions (-pthread)
|
||||
|
||||
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pthread")
|
||||
set (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pthread")
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pthread")
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
#
|
||||
# Global Configuration for windows platform
|
||||
#
|
||||
|
||||
# define some preprocessor flags
|
||||
add_definitions(/DWIN32_LEAN_AND_MEAN /D_UNICODE /DUNICODE /W4)
|
|
@ -1,13 +0,0 @@
|
|||
# jsoncons cmake module
|
||||
# This module sets the following variables in your project::
|
||||
#
|
||||
# jsoncons_FOUND - true if jsoncons found on the system
|
||||
# jsoncons_INCLUDE_DIRS - the directory containing jsoncons headers
|
||||
# jsoncons_LIBRARY - empty
|
||||
|
||||
@PACKAGE_INIT@
|
||||
|
||||
if(NOT TARGET @PROJECT_NAME@)
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
|
||||
get_target_property(@PROJECT_NAME@_INCLUDE_DIRS jsoncons INTERFACE_INCLUDE_DIRECTORIES)
|
||||
endif()
|
|
@ -1 +0,0 @@
|
|||
|
|
@ -1,64 +0,0 @@
|
|||
All core jsoncons classes and functions are in namespace `jsoncons`.
|
||||
|
||||
#### Unpacked Representation
|
||||
|
||||
[json](ref/json.md)
|
||||
[json_parser](ref/json_parser.md)
|
||||
[json_reader](ref/json_reader.md)
|
||||
[json_decoder](ref/json_decoder.md)
|
||||
|
||||
[ojson](ref/ojson.md)
|
||||
|
||||
[wjson](ref/wjson.md)
|
||||
[wjson_reader](ref/wjson_reader.md)
|
||||
|
||||
[wojson](ref/wojson.md)
|
||||
|
||||
#### C++/JSON Conversion
|
||||
|
||||
[encode_json](ref/encode_json.md)
|
||||
[decode_json](ref/decode_json.md)
|
||||
|
||||
#### Streaming
|
||||
|
||||
[json_content_handler](ref/json_content_handler.md)
|
||||
[json_encoder](ref/json_encoder.md)
|
||||
[json_options](ref/json_options.md)
|
||||
|
||||
[wjson_encoder](ref/wjson_encoder.md)
|
||||
[wjson_options](ref/wjson_options.md)
|
||||
|
||||
[json_filter](ref/json_filter.md)
|
||||
[rename_object_member_filter](ref/rename_object_member_filter.md)
|
||||
|
||||
[json_cursor](ref/json_cursor.md)
|
||||
[staj_reader](ref/staj_reader.md)
|
||||
[staj_object_iterator](ref/staj_object_iterator.md)
|
||||
[staj_array_iterator](ref/staj_array_iterator.md)
|
||||
|
||||
### Extensions
|
||||
|
||||
#### [jsonpointer](ref/jsonpointer/jsonpointer.md)
|
||||
|
||||
#### [jsonpatch](ref/jsonpatch/jsonpatch.md)
|
||||
|
||||
#### [jsonpath](ref/jsonpath/jsonpath.md)
|
||||
|
||||
#### [cbor](ref/cbor/cbor.md)
|
||||
|
||||
#### [msgpack](ref/msgpack/msgpack.md)
|
||||
|
||||
#### [ubjson](ref/ubjson/ubjson.md)
|
||||
|
||||
#### [msgpack](ref/msgpack/msgpack.md)
|
||||
|
||||
#### [bson](ref/bson/bson.md)
|
||||
|
||||
### Tutorials
|
||||
|
||||
[Basics](Tutorials/Basics.md)
|
||||
|
||||
[Custom Allocators](Tutorials/Custom%20Allocators.md)
|
||||
|
||||
[Unicode support](Tutorials/Unicode%20support.md)
|
||||
|
|
@ -1,812 +0,0 @@
|
|||
# jsoncons: a C++ library for json construction
|
||||
|
||||
[Preliminaries](#A1)
|
||||
|
||||
[Reading JSON text from a file](#A2)
|
||||
|
||||
[Constructing json values in C++](#A3)
|
||||
|
||||
[Conversion between JSON and C++ data structures](#A4)
|
||||
|
||||
[Converting CSV files to json](#A5 )
|
||||
|
||||
[Pretty print](#A6)
|
||||
|
||||
[Filters](#A7)
|
||||
|
||||
[JSONPath](#A8)
|
||||
|
||||
[About jsoncons::json](#A9)
|
||||
|
||||
[Wide character support](#A10)
|
||||
|
||||
[ojson and wojson](#A11)
|
||||
|
||||
<div id="A1"/>
|
||||
### Preliminaries
|
||||
|
||||
jsoncons is a C++, header-only library for constructing [JSON](http://www.json.org) and JSON-like
|
||||
data formats such as [CBOR](http://cbor.io/). It supports
|
||||
|
||||
- Parsing JSON-like text or binary formats into a tree model
|
||||
that defines an interface for accessing and modifying that data (covers bignum and byte string values.)
|
||||
|
||||
- Serializing the tree model into different JSON-like text or binary formats.
|
||||
|
||||
- Converting from JSON-like text or binary formats to C++ data structures and back via [json_type_traits](https://github.com/danielaparker/jsoncons/blob/master/doc/ref/json_type_traits.md).
|
||||
|
||||
- Streaming JSON read and write events, somewhat analogously to SAX (push parsing) and StAX (pull parsing) in the XML world.
|
||||
|
||||
The jsoncons library is header-only: it consists solely of header files containing templates and inline functions, and requires no separately-compiled library binaries when linking. It has no dependence on other libraries.
|
||||
|
||||
To install the librray, download the [latest release](https://github.com/danielaparker/jsoncons/releases) and unpack the zip file. Copy the directory `include/jsoncons` to your `include` directory. If you wish to use extensions, copy `include/jsoncons_ext` as well.
|
||||
|
||||
Or, download the latest code on [master](https://github.com/danielaparker/jsoncons/archive/master.zip).
|
||||
|
||||
Compared to other JSON libraries, jsoncons has been designed to handle very large JSON texts. At its heart are
|
||||
SAX style parsers and serializers. Its [json parser](https://github.com/danielaparker/jsoncons/blob/master/doc/ref/json_parser.md) is an
|
||||
incremental parser that can be fed its input in chunks, and does not require an entire file to be loaded in memory at one time.
|
||||
Its tree model is more compact than most, and can be made more compact still with a user-supplied
|
||||
allocator. It also supports memory efficient parsing of very large JSON texts with a [pull parser](https://github.com/danielaparker/jsoncons/blob/master/doc/ref/json_cursor.md),
|
||||
built on top of its incremental parser.
|
||||
|
||||
The [jsoncons data model](https://github.com/danielaparker/jsoncons/blob/master/doc/ref/data-model.md) supports the familiar JSON types - nulls,
|
||||
booleans, numbers, strings, arrays, objects - plus byte strings. In addition, jsoncons
|
||||
supports semantic tagging of date-time values, timestamp values, big integers,
|
||||
big decimals, bigfloats and binary encodings. This allows it to preserve these type semantics when parsing
|
||||
JSON-like data formats such as CBOR that have them.
|
||||
|
||||
The jsoncons classes and functions are in namespace `jsoncons`. You need to include the header file
|
||||
```c++
|
||||
#include <jsoncons/json.hpp>
|
||||
```
|
||||
and, for convenience,
|
||||
```c++
|
||||
using jsoncons::json;
|
||||
```
|
||||
|
||||
<div id="A2"/>
|
||||
### Reading JSON text from a file
|
||||
|
||||
Example file (`books.json`):
|
||||
```c++
|
||||
[
|
||||
{
|
||||
"title" : "Kafka on the Shore",
|
||||
"author" : "Haruki Murakami",
|
||||
"price" : 25.17
|
||||
},
|
||||
{
|
||||
"title" : "Women: A Novel",
|
||||
"author" : "Charles Bukowski",
|
||||
"price" : 12.0
|
||||
},
|
||||
{
|
||||
"title" : "Cutter's Way",
|
||||
"author" : "Ivan Passer"
|
||||
}
|
||||
]
|
||||
```
|
||||
It consists of an array of book elements, each element is an object with members title, author, and price.
|
||||
|
||||
Read the JSON text into a `json` value,
|
||||
```c++
|
||||
std::ifstream is("books.json");
|
||||
json books = json::parse(is);
|
||||
```
|
||||
Loop through the book array elements, using a range-based for loop
|
||||
```c++
|
||||
for (const auto& book : books.array_range())
|
||||
{
|
||||
std::string author = book["author"].as<std::string>();
|
||||
std::string title = book["title"].as<std::string>();
|
||||
std::cout << author << ", " << title << std::endl;
|
||||
}
|
||||
```
|
||||
or begin-end iterators
|
||||
```c++
|
||||
for (auto it = books.array_range().begin();
|
||||
it != books.array_range().end();
|
||||
++it)
|
||||
{
|
||||
std::string author = (*it)["author"].as<std::string>();
|
||||
std::string title = (*it)["title"].as<std::string>();
|
||||
std::cout << author << ", " << title << std::endl;
|
||||
}
|
||||
```
|
||||
or a traditional for loop
|
||||
```c++
|
||||
for (size_t i = 0; i < books.size(); ++i)
|
||||
{
|
||||
json& book = books[i];
|
||||
std::string author = book["author"].as<std::string>();
|
||||
std::string title = book["title"].as<std::string>();
|
||||
std::cout << author << ", " << title << std::endl;
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```
|
||||
Haruki Murakami, Kafka on the Shore
|
||||
Charles Bukowski, Women: A Novel
|
||||
Ivan Passer, Cutter's Way
|
||||
```
|
||||
|
||||
Loop through the members of the third book element, using a range-based for loop
|
||||
|
||||
```c++
|
||||
for (const auto& member : books[2].object_range())
|
||||
{
|
||||
std::cout << member.key() << "="
|
||||
<< member.value() << std::endl;
|
||||
}
|
||||
```
|
||||
|
||||
or begin-end iterators:
|
||||
|
||||
```c++
|
||||
for (auto it = books[2].object_range().begin();
|
||||
it != books[2].object_range().end();
|
||||
++it)
|
||||
{
|
||||
std::cout << (*it).key() << "="
|
||||
<< (*it).value() << std::endl;
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```
|
||||
author=Ivan Passer
|
||||
title=Cutter's Way
|
||||
```
|
||||
|
||||
Note that the third book, Cutter's Way, is missing a price.
|
||||
|
||||
You have a choice of object member accessors:
|
||||
|
||||
- `book["price"]` will throw `std::out_of_range` if there is no price
|
||||
- `book.get_with_default("price",std::string("n/a"))` will return the price converted to the
|
||||
default's data type, `std::string`, or `"n/a"` if there is no price.
|
||||
|
||||
So if you want to show "n/a" for the missing price, you can use this accessor
|
||||
```c++
|
||||
std::string price = book.get_with_default("price","n/a");
|
||||
```
|
||||
Or you can check if book has a member "price" with the method `contains`, and output accordingly,
|
||||
```c++
|
||||
if (book.contains("price"))
|
||||
{
|
||||
double price = book["price"].as<double>();
|
||||
std::cout << price;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "n/a";
|
||||
}
|
||||
```
|
||||
<div id="A3"/>
|
||||
### Constructing json values in C++
|
||||
|
||||
The default `json` constructor produces an empty json object. For example
|
||||
```c++
|
||||
json image_sizing;
|
||||
std::cout << image_sizing << std::endl;
|
||||
```
|
||||
produces
|
||||
```json
|
||||
{}
|
||||
```
|
||||
To construct a json object with members, take an empty json object and set some name-value pairs
|
||||
```c++
|
||||
image_sizing.insert_or_assign("Resize To Fit",true); // a boolean
|
||||
image_sizing.insert_or_assign("Resize Unit", "pixels"); // a string
|
||||
image_sizing.insert_or_assign("Resize What", "long_edge"); // a string
|
||||
image_sizing.insert_or_assign("Dimension 1",9.84); // a double
|
||||
image_sizing.insert_or_assign("Dimension 2",json::null()); // a null value
|
||||
```
|
||||
|
||||
Or, use an object initializer-list:
|
||||
```c++
|
||||
json file_settings = json::object{
|
||||
{"Image Format", "JPEG"},
|
||||
{"Color Space", "sRGB"},
|
||||
{"Limit File Size", true},
|
||||
{"Limit File Size To", 10000}
|
||||
};
|
||||
```
|
||||
|
||||
To construct a json array, initialize with the array type
|
||||
```c++
|
||||
json color_spaces = json::array();
|
||||
```
|
||||
and add some elements
|
||||
```c++
|
||||
color_spaces.push_back("sRGB");
|
||||
color_spaces.push_back("AdobeRGB");
|
||||
color_spaces.push_back("ProPhoto RGB");
|
||||
```
|
||||
|
||||
Or, use an array initializer-list:
|
||||
```c++
|
||||
json image_formats = json::array{"JPEG","PSD","TIFF","DNG"};
|
||||
```
|
||||
|
||||
The `operator[]` provides another way for setting name-value pairs.
|
||||
```c++
|
||||
json file_export;
|
||||
file_export["File Format Options"]["Color Spaces"] =
|
||||
std::move(color_spaces);
|
||||
file_export["File Format Options"]["Image Formats"] =
|
||||
std::move(image_formats);
|
||||
file_export["File Settings"] = std::move(file_settings);
|
||||
file_export["Image Sizing"] = std::move(image_sizing);
|
||||
```
|
||||
Note that if `file_export["File Format Options"]` doesn't exist,
|
||||
```c++
|
||||
file_export["File Format Options"]["Color Spaces"] =
|
||||
std::move(color_spaces)
|
||||
```
|
||||
creates `"File Format Options"` as an object and puts `"Color Spaces"` in it.
|
||||
|
||||
Serializing
|
||||
```c++
|
||||
std::cout << pretty_print(file_export) << std::endl;
|
||||
```
|
||||
produces
|
||||
```json
|
||||
{
|
||||
"File Format Options": {
|
||||
"Color Spaces": ["sRGB","AdobeRGB","ProPhoto RGB"],
|
||||
"Image Formats": ["JPEG","PSD","TIFF","DNG"]
|
||||
},
|
||||
"File Settings": {
|
||||
"Color Space": "sRGB",
|
||||
"Image Format": "JPEG",
|
||||
"Limit File Size": true,
|
||||
"Limit File Size To": 10000
|
||||
},
|
||||
"Image Sizing": {
|
||||
"Dimension 1": 9.84,
|
||||
"Dimension 2": null,
|
||||
"Resize To Fit": true,
|
||||
"Resize Unit": "pixels",
|
||||
"Resize What": "long_edge"
|
||||
}
|
||||
}
|
||||
```
|
||||
<div id="A4"/>
|
||||
### Conversion between JSON and C++ data structures
|
||||
|
||||
jsoncons supports conversion between JSON text and C++ data structures. The functions [decode_json](https://github.com/danielaparker/jsoncons/blob/master/doc/ref/decode_json.md)
|
||||
and [encode_json](https://github.com/danielaparker/jsoncons/blob/master/doc/ref/encode_json.md) convert JSON formatted strings or streams to C++ data structures and back.
|
||||
Decode and encode work for all C++ classes that have
|
||||
[json_type_traits](https://github.com/danielaparker/jsoncons/blob/master/doc/ref/json_type_traits.md)
|
||||
defined. The standard library containers are already supported, and you can specialize `json_type_traits`
|
||||
for your own types in the `jsoncons` namespace.
|
||||
|
||||
`JSONCONS_MEMBER_TRAITS_DECL` is a macro that simplifies the creation of the necessary boilerplate
|
||||
for your own types.
|
||||
|
||||
```c++
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <jsoncons/json.hpp>
|
||||
|
||||
using namespace jsoncons;
|
||||
|
||||
namespace ns {
|
||||
|
||||
struct reputon
|
||||
{
|
||||
std::string rater;
|
||||
std::string assertion;
|
||||
std::string rated;
|
||||
double rating;
|
||||
|
||||
friend bool operator==(const reputon& lhs, const reputon& rhs)
|
||||
{
|
||||
return lhs.rater == rhs.rater &&
|
||||
lhs.assertion == rhs.assertion &&
|
||||
lhs.rated == rhs.rated &&
|
||||
lhs.rating == rhs.rating;
|
||||
}
|
||||
|
||||
friend bool operator!=(const reputon& lhs, const reputon& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
};
|
||||
};
|
||||
|
||||
class reputation_object
|
||||
{
|
||||
std::string application;
|
||||
std::vector<reputon> reputons;
|
||||
|
||||
// Make json_type_traits specializations friends to give accesses to private members
|
||||
JSONCONS_TYPE_TRAITS_FRIEND;
|
||||
public:
|
||||
reputation_object()
|
||||
{
|
||||
}
|
||||
reputation_object(const std::string& application, const std::vector<reputon>& reputons)
|
||||
: application(application), reputons(reputons)
|
||||
{}
|
||||
|
||||
friend bool operator==(const reputation_object& lhs, const reputation_object& rhs)
|
||||
{
|
||||
if (lhs.application != rhs.application)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (lhs.reputons.size() != rhs.reputons.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < lhs.reputons.size(); ++i)
|
||||
{
|
||||
if (lhs.reputons[i] != rhs.reputons[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
friend bool operator!=(const reputation_object& lhs, const reputation_object& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace ns
|
||||
|
||||
// Declare the traits. Specify which data members need to be serialized.
|
||||
JSONCONS_MEMBER_TRAITS_DECL(ns::reputon, rater, assertion, rated, rating)
|
||||
JSONCONS_MEMBER_TRAITS_DECL(ns::reputation_object, application, reputons)
|
||||
|
||||
int main()
|
||||
{
|
||||
ns::reputation_object val("hiking", { ns::reputon{"HikingAsylum.example.com","strong-hiker","Marilyn C",0.90} });
|
||||
|
||||
std::string s;
|
||||
encode_json(val, s, indenting::indent);
|
||||
std::cout << s << "\n";
|
||||
|
||||
auto val2 = decode_json<ns::reputation_object>(s);
|
||||
|
||||
assert(val2 == val);
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```
|
||||
{
|
||||
"application": "hiking",
|
||||
"reputons": [
|
||||
{
|
||||
"assertion": "strong-hiker",
|
||||
"rated": "Marilyn C",
|
||||
"rater": "HikingAsylum.example.com",
|
||||
"rating": 0.9
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
See [examples](https://github.com/danielaparker/jsoncons/blob/master/doc/Examples.md#G1)
|
||||
|
||||
<div id="A5"/>
|
||||
### Converting CSV files to json
|
||||
|
||||
Example CSV file (tasks.csv):
|
||||
|
||||
```
|
||||
project_id, task_name, task_start, task_finish
|
||||
4001,task1,01/01/2003,01/31/2003
|
||||
4001,task2,02/01/2003,02/28/2003
|
||||
4001,task3,03/01/2003,03/31/2003
|
||||
4002,task1,04/01/2003,04/30/2003
|
||||
4002,task2,05/01/2003,
|
||||
```
|
||||
|
||||
You can read the `CSV` file into a `json` value with the `decode_csv` function.
|
||||
|
||||
```c++
|
||||
#include <fstream>
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons_ext/csv/csv_reader.hpp>
|
||||
#include <jsoncons_ext/csv/csv_encoder.hpp>
|
||||
|
||||
using namespace jsoncons;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::ifstream is("input/tasks.csv");
|
||||
|
||||
csv::csv_options options;
|
||||
options.assume_header(true)
|
||||
.trim(true)
|
||||
.ignore_empty_values(true)
|
||||
.column_types("integer,string,string,string");
|
||||
ojson tasks = csv::decode_csv<ojson>(is, options);
|
||||
|
||||
std::cout << "(1)\n" << pretty_print(tasks) << "\n\n";
|
||||
|
||||
std::cout << "(2)\n";
|
||||
csv::encode_csv(tasks, std::cout);
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```json
|
||||
(1)
|
||||
[
|
||||
{
|
||||
"project_id": 4001,
|
||||
"task_name": "task1",
|
||||
"task_start": "01/01/2003",
|
||||
"task_finish": "01/31/2003"
|
||||
},
|
||||
{
|
||||
"project_id": 4001,
|
||||
"task_name": "task2",
|
||||
"task_start": "02/01/2003",
|
||||
"task_finish": "02/28/2003"
|
||||
},
|
||||
{
|
||||
"project_id": 4001,
|
||||
"task_name": "task3",
|
||||
"task_start": "03/01/2003",
|
||||
"task_finish": "03/31/2003"
|
||||
},
|
||||
{
|
||||
"project_id": 4002,
|
||||
"task_name": "task1",
|
||||
"task_start": "04/01/2003",
|
||||
"task_finish": "04/30/2003"
|
||||
},
|
||||
{
|
||||
"project_id": 4002,
|
||||
"task_name": "task2",
|
||||
"task_start": "05/01/2003"
|
||||
}
|
||||
]
|
||||
```
|
||||
There are a few things to note about the effect of the parameter settings.
|
||||
- `assume_header` `true` tells the csv parser to parse the first line of the file for column names, which become object member names.
|
||||
- `trim` `true` tells the parser to trim leading and trailing whitespace, in particular, to remove the leading whitespace in the column names.
|
||||
- `ignore_empty_values` `true` causes the empty last value in the `task_finish` column to be omitted.
|
||||
- The `column_types` setting specifies that column one ("project_id") contains integers and the remaining columns strings.
|
||||
|
||||
<div id="A6"/>
|
||||
### Pretty print
|
||||
|
||||
The `pretty_print` function applies stylistic formatting to JSON text. For example
|
||||
|
||||
```c++
|
||||
json val;
|
||||
|
||||
val["verts"] = json::array{1, 2, 3};
|
||||
val["normals"] = json::array{1, 0, 1};
|
||||
val["uvs"] = json::array{0, 0, 1, 1};
|
||||
|
||||
std::cout << pretty_print(val) << std::endl;
|
||||
```
|
||||
produces
|
||||
|
||||
```json
|
||||
{
|
||||
"normals": [1,0,1],
|
||||
"uvs": [0,0,1,1],
|
||||
"verts": [1,2,3]
|
||||
}
|
||||
```
|
||||
By default, within objects, arrays of scalar values are displayed on the same line.
|
||||
|
||||
The `pretty_print` function takes an optional second parameter, [json_options](https://github.com/danielaparker/jsoncons/blob/master/doc/ref/json_options.md), that allows custom formatting of output.
|
||||
To display the array scalar values on a new line, set the `object_array_line_splits` property to `line_split_kind::new_line`. The code
|
||||
```c++
|
||||
json_options options;
|
||||
format.object_array_line_splits(line_split_kind::new_line);
|
||||
std::cout << pretty_print(val,options) << std::endl;
|
||||
```
|
||||
produces
|
||||
```json
|
||||
{
|
||||
"normals": [
|
||||
1,0,1
|
||||
],
|
||||
"uvs": [
|
||||
0,0,1,1
|
||||
],
|
||||
"verts": [
|
||||
1,2,3
|
||||
]
|
||||
}
|
||||
```
|
||||
To display the elements of array values on multiple lines, set the `object_array_line_splits` property to `line_split_kind::multi_line`. The code
|
||||
```c++
|
||||
json_options options;
|
||||
format.object_array_line_splits(line_split_kind::multi_line);
|
||||
std::cout << pretty_print(val,options) << std::endl;
|
||||
```
|
||||
produces
|
||||
```json
|
||||
{
|
||||
"normals": [
|
||||
1,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"uvs": [
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1
|
||||
],
|
||||
"verts": [
|
||||
1,
|
||||
2,
|
||||
3
|
||||
]
|
||||
}
|
||||
```
|
||||
<div id="A7"/>
|
||||
### Filters
|
||||
|
||||
You can rename object member names with the built in filter [rename_object_member_filter](https://github.com/danielaparker/jsoncons/blob/master/doc/ref/rename_object_member_filter.md)
|
||||
|
||||
```c++
|
||||
#include <sstream>
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons/json_filter.hpp>
|
||||
|
||||
using namespace jsoncons;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::string s = R"({"first":1,"second":2,"fourth":3,"fifth":4})";
|
||||
|
||||
json_encoder encoder(std::cout);
|
||||
|
||||
// Filters can be chained
|
||||
rename_object_member_filter filter2("fifth", "fourth", encoder);
|
||||
rename_object_member_filter filter1("fourth", "third", filter2);
|
||||
|
||||
// A filter can be passed to any function that takes
|
||||
// a json_content_handler ...
|
||||
std::cout << "(1) ";
|
||||
std::istringstream is(s);
|
||||
json_reader reader(is, filter1);
|
||||
reader.read();
|
||||
std::cout << std::endl;
|
||||
|
||||
// or a json_content_handler
|
||||
std::cout << "(2) ";
|
||||
ojson j = ojson::parse(s);
|
||||
j.dump(filter1);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```json
|
||||
(1) {"first":1,"second":2,"third":3,"fourth":4}
|
||||
(2) {"first":1,"second":2,"third":3,"fourth":4}
|
||||
```
|
||||
Or define and use your own filters. See [json_filter](https://github.com/danielaparker/jsoncons/blob/master/doc/ref/json_filter.md) for details.
|
||||
<div id="A8"/>
|
||||
### JSONPath
|
||||
|
||||
[Stefan Goessner's JSONPath](http://goessner.net/articles/JsonPath/) is an XPATH inspired query language for selecting parts of a JSON structure.
|
||||
|
||||
Example JSON file (booklist.json):
|
||||
```json
|
||||
{ "store": {
|
||||
"book": [
|
||||
{ "category": "reference",
|
||||
"author": "Nigel Rees",
|
||||
"title": "Sayings of the Century",
|
||||
"price": 8.95
|
||||
},
|
||||
{ "category": "fiction",
|
||||
"author": "Evelyn Waugh",
|
||||
"title": "Sword of Honour",
|
||||
"price": 12.99
|
||||
},
|
||||
{ "category": "fiction",
|
||||
"author": "Herman Melville",
|
||||
"title": "Moby Dick",
|
||||
"isbn": "0-553-21311-3",
|
||||
"price": 8.99
|
||||
},
|
||||
{ "category": "fiction",
|
||||
"author": "J. R. R. Tolkien",
|
||||
"title": "The Lord of the Rings",
|
||||
"isbn": "0-395-19395-8",
|
||||
"price": 22.99
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
JSONPath examples:
|
||||
```c++
|
||||
#include <jsoncons_ext/jsonpath/json_query.hpp>
|
||||
|
||||
using jsoncons::jsonpath::json_query;
|
||||
|
||||
std::ifstream is("./input/booklist.json");
|
||||
json booklist = json::parse(is);
|
||||
|
||||
// The authors of books that are cheaper than $10
|
||||
json result1 = json_query(booklist, "$.store.book[?(@.price < 10)].author");
|
||||
std::cout << "(1) " << result1 << std::endl;
|
||||
|
||||
// The number of books
|
||||
json result2 = json_query(booklist, "$..book.length");
|
||||
std::cout << "(2) " << result2 << std::endl;
|
||||
|
||||
// The third book
|
||||
json result3 = json_query(booklist, "$..book[2]");
|
||||
std::cout << "(3)\n" << pretty_print(result3) << std::endl;
|
||||
|
||||
// All books whose author's name starts with Evelyn
|
||||
json result4 = json_query(booklist, "$.store.book[?(@.author =~ /Evelyn.*?/)]");
|
||||
std::cout << "(4)\n" << pretty_print(result4) << std::endl;
|
||||
|
||||
// The titles of all books that have isbn number
|
||||
json result5 = json_query(booklist, "$..book[?(@.isbn)].title");
|
||||
std::cout << "(5) " << result5 << std::endl;
|
||||
|
||||
// All authors and titles of books
|
||||
json result6 = json_query(booklist, "$['store']['book']..['author','title']");
|
||||
std::cout << "(6)\n" << pretty_print(result6) << std::endl;
|
||||
```
|
||||
Output:
|
||||
```json
|
||||
(1) ["Nigel Rees","Herman Melville"]
|
||||
(2) [4]
|
||||
(3)
|
||||
[
|
||||
{
|
||||
"author": "Herman Melville",
|
||||
"category": "fiction",
|
||||
"isbn": "0-553-21311-3",
|
||||
"price": 8.99,
|
||||
"title": "Moby Dick"
|
||||
}
|
||||
]
|
||||
(4)
|
||||
[
|
||||
{
|
||||
"author": "Evelyn Waugh",
|
||||
"category": "fiction",
|
||||
"price": 12.99,
|
||||
"title": "Sword of Honour"
|
||||
}
|
||||
]
|
||||
(5) ["Moby Dick","The Lord of the Rings"]
|
||||
(6)
|
||||
[
|
||||
"Nigel Rees",
|
||||
"Sayings of the Century",
|
||||
"Evelyn Waugh",
|
||||
"Sword of Honour",
|
||||
"Herman Melville",
|
||||
"Moby Dick",
|
||||
"J. R. R. Tolkien",
|
||||
"The Lord of the Rings"
|
||||
]
|
||||
```
|
||||
<div id="A9"/>
|
||||
### About jsoncons::json
|
||||
|
||||
The [json](https://github.com/danielaparker/jsoncons/blob/master/doc/ref/json.md) class is an instantiation of the `basic_json` class template that uses `char` as the character type
|
||||
and sorts object members in alphabetically order.
|
||||
```c++
|
||||
typedef basic_json<char,
|
||||
ImplementationPolicy = sorted_policy,
|
||||
Allocator = std::allocator<char>> json;
|
||||
```
|
||||
If you prefer to retain the original insertion order, use [ojson](https://github.com/danielaparker/jsoncons/blob/master/doc/ref/ojson.md) instead.
|
||||
|
||||
The library includes an instantiation for wide characters as well, [wjson](https://github.com/danielaparker/jsoncons/blob/master/ref/doc/wjson.md)
|
||||
```c++
|
||||
typedef basic_json<wchar_t,
|
||||
ImplementationPolicy = sorted_policy,
|
||||
Allocator = std::allocator<wchar_t>> wjson;
|
||||
```
|
||||
If you prefer to retain the original insertion order, use [wojson](https://github.com/danielaparker/jsoncons/blob/master/doc/ref/wojson.md) instead.
|
||||
|
||||
Note that the allocator type allows you to supply a custom allocator. For example, you can use the boost [fast_pool_allocator](http://www.boost.org/doc/libs/1_60_0/libs/pool/doc/html/boost/fast_pool_allocator.html):
|
||||
```c++
|
||||
#include <boost/pool/pool_alloc.hpp>
|
||||
#include <jsoncons/json.hpp>
|
||||
|
||||
typedef jsoncons::basic_json<char, boost::fast_pool_allocator<char>> myjson;
|
||||
|
||||
myjson o;
|
||||
|
||||
o.insert_or_assign("FirstName","Joe");
|
||||
o.insert_or_assign("LastName","Smith");
|
||||
```
|
||||
This results in a json value being constucted with all memory being allocated from the boost memory pool. (In this particular case there is no improvement in performance over `std::allocator`.)
|
||||
|
||||
Note that the underlying memory pool used by the `boost::fast_pool_allocator` is never freed.
|
||||
|
||||
<div id="A10"/>
|
||||
### Wide character support
|
||||
|
||||
jsoncons supports wide character strings and streams with `wjson` and `wjson_reader`. It supports `UTF16` encoding if `wchar_t` has size 2 (Windows) and `UTF32` encoding if `wchar_t` has size 4. You can construct a `wjson` value in exactly the same way as a `json` value, for instance:
|
||||
```c++
|
||||
using jsoncons::wjson;
|
||||
|
||||
wjson root;
|
||||
root[L"field1"] = L"test";
|
||||
root[L"field2"] = 3.9;
|
||||
root[L"field3"] = true;
|
||||
|
||||
std::wcout << root << L"\n";
|
||||
```
|
||||
which prints
|
||||
```c++
|
||||
{"field1":"test","field2":3.9,"field3":true}
|
||||
```
|
||||
<div id="A11"/>
|
||||
### ojson and wojson
|
||||
|
||||
The [ojson](https://github.com/danielaparker/jsoncons/blob/master/doc/ref/ojson.md) ([wojson](https://github.com/danielaparker/jsoncons/blob/master/doc/ref/wojson.md)) class is an instantiation of the `basic_json` class template that uses `char` (`wchar_t`) as the character type and keeps object members in their original order.
|
||||
```c++
|
||||
ojson o = ojson::parse(R"(
|
||||
{
|
||||
"street_number" : "100",
|
||||
"street_name" : "Queen St W",
|
||||
"city" : "Toronto",
|
||||
"country" : "Canada"
|
||||
}
|
||||
)");
|
||||
|
||||
std::cout << pretty_print(o) << std::endl;
|
||||
```
|
||||
Output:
|
||||
```json
|
||||
{
|
||||
"street_number": "100",
|
||||
"street_name": "Queen St W",
|
||||
"city": "Toronto",
|
||||
"country": "Canada"
|
||||
}
|
||||
```
|
||||
Insert "postal_code" at end
|
||||
```c++
|
||||
o.insert_or_assign("postal_code", "M5H 2N2");
|
||||
|
||||
std::cout << pretty_print(o) << std::endl;
|
||||
```
|
||||
Output:
|
||||
```json
|
||||
{
|
||||
"street_number": "100",
|
||||
"street_name": "Queen St W",
|
||||
"city": "Toronto",
|
||||
"country": "Canada",
|
||||
"postal_code": "M5H 2N2"
|
||||
}
|
||||
```
|
||||
Insert "province" before "country"
|
||||
```c++
|
||||
auto it = o.find("country");
|
||||
o.insert_or_assign(it,"province","Ontario");
|
||||
|
||||
std::cout << pretty_print(o) << std::endl;
|
||||
```
|
||||
Output:
|
||||
```json
|
||||
{
|
||||
"street_number": "100",
|
||||
"street_name": "Queen St W",
|
||||
"city": "Toronto",
|
||||
"province": "Ontario",
|
||||
"country": "Canada",
|
||||
"postal_code": "M5H 2N2"
|
||||
}
|
||||
```
|
||||
|
||||
For more information, consult the latest [examples](https://github.com/danielaparker/jsoncons/blob/master/doc/Examples.md), [documentation](https://github.com/danielaparker/jsoncons/blob/master/doc/Home.md) and [roadmap](https://github.com/danielaparker/jsoncons/blob/master/Roadmap.md).
|
||||
|
|
@ -1,448 +0,0 @@
|
|||
## Examples
|
||||
|
||||
The examples below illustrate the use of the [json](../ref/json.md) class and [json_query](../ref/jsonpath/json_query.md) function.
|
||||
|
||||
### json construction
|
||||
|
||||
```c++
|
||||
#include <jsoncons/json.hpp>
|
||||
|
||||
// For convenience
|
||||
using jsoncons::json;
|
||||
|
||||
// Construct a book object
|
||||
json book1;
|
||||
|
||||
book1["category"] = "Fiction";
|
||||
book1["title"] = "A Wild Sheep Chase: A Novel";
|
||||
book1["author"] = "Haruki Murakami";
|
||||
book1["date"] = "2002-04-09";
|
||||
book1["price"] = 9.01;
|
||||
book1["isbn"] = "037571894X";
|
||||
|
||||
// Construct another using the insert_or_assign function
|
||||
json book2;
|
||||
|
||||
book2.insert_or_assign("category", "History");
|
||||
book2.insert_or_assign("title", "Charlie Wilson's War");
|
||||
book2.insert_or_assign("author", "George Crile");
|
||||
book2.insert_or_assign("date", "2007-11-06");
|
||||
book2.insert_or_assign("price", 10.50);
|
||||
book2.insert_or_assign("isbn", "0802143415");
|
||||
|
||||
// Use insert_or_assign again, but more efficiently
|
||||
json book3;
|
||||
|
||||
// Reserve memory, to avoid reallocations
|
||||
book3.reserve(6);
|
||||
|
||||
// Insert in name alphabetical order
|
||||
// Give insert_or_assign a hint where to insert the next member
|
||||
auto hint = book3.insert_or_assign(book3.object_range().begin(),"author", "Haruki Murakami");
|
||||
hint = book3.insert_or_assign(hint, "category", "Fiction");
|
||||
hint = book3.insert_or_assign(hint, "date", "2006-01-03");
|
||||
hint = book3.insert_or_assign(hint, "isbn", "1400079276");
|
||||
hint = book3.insert_or_assign(hint, "price", 13.45);
|
||||
hint = book3.insert_or_assign(hint, "title", "Kafka on the Shore");
|
||||
|
||||
// Construct a fourth from a string
|
||||
json book4 = json::parse(R"(
|
||||
{
|
||||
"category" : "Fiction",
|
||||
"title" : "Pulp",
|
||||
"author" : "Charles Bukowski",
|
||||
"date" : "2004-07-08",
|
||||
"price" : 22.48,
|
||||
"isbn" : "1852272007"
|
||||
}
|
||||
)");
|
||||
|
||||
// Construct a booklist array
|
||||
|
||||
json booklist = json::array();
|
||||
|
||||
// For efficiency, reserve memory, to avoid reallocations
|
||||
booklist.reserve(4);
|
||||
|
||||
// For efficency, tell jsoncons to move the contents
|
||||
// of the four book objects into the array
|
||||
booklist.add(std::move(book1));
|
||||
booklist.add(std::move(book2));
|
||||
|
||||
// Add the third book to the front
|
||||
auto pos = booklist.add(booklist.array_range().begin(),std::move(book3));
|
||||
|
||||
// and the last one immediately after
|
||||
booklist.add(pos+1,std::move(book4));
|
||||
|
||||
// See what's left of book1, 2, 3 and 4 (expect nulls)
|
||||
std::cout << book1 << "," << book2 << "," << book3 << "," << book4 << std::endl;
|
||||
|
||||
|
||||
++
|
||||
//Loop through the booklist elements using a range-based for loop
|
||||
for (const auto& book : booklist.array_range())
|
||||
{
|
||||
std::cout << book["title"].as<std::string>()
|
||||
<< ","
|
||||
<< book["price"].as<double>() << std::endl;
|
||||
}
|
||||
|
||||
// The second book
|
||||
json& book = booklist[1];
|
||||
|
||||
//Loop through the book's name-value pairs using a range-based for loop
|
||||
for (const auto& member : book.object_range())
|
||||
{
|
||||
std::cout << member.key()
|
||||
<< ","
|
||||
<< member.value() << std::endl;
|
||||
}
|
||||
|
||||
auto it = book.find("author");
|
||||
if (it != book.object_range().end())
|
||||
{
|
||||
// member "author" found
|
||||
}
|
||||
|
||||
if (book.contains("author"))
|
||||
{
|
||||
// book has a member "author"
|
||||
}
|
||||
|
||||
book.get("author", "author unknown").as<std::string>();
|
||||
// Returns author if found, otherwise "author unknown"
|
||||
|
||||
try
|
||||
{
|
||||
book["ratings"].as<std::string>();
|
||||
}
|
||||
catch (const std::out_of_range& e)
|
||||
{
|
||||
// member "ratings" not found
|
||||
}
|
||||
|
||||
// Add ratings
|
||||
book["ratings"]["*****"] = 4;
|
||||
book["ratings"]["*"] = 2;
|
||||
|
||||
// Delete one-star ratings
|
||||
book["ratings"].erase("*");
|
||||
|
||||
```
|
||||
```c++
|
||||
// Serialize the booklist to a file
|
||||
std::ofstream os("booklist.json");
|
||||
os << pretty_print(booklist);
|
||||
```
|
||||
|
||||
The JSON output `booklist.json`
|
||||
```json
|
||||
[
|
||||
{
|
||||
"author":"Haruki Murakami",
|
||||
"category":"Fiction",
|
||||
"date":"2006-01-03",
|
||||
"isbn":"1400079276",
|
||||
"price":13.45,
|
||||
"title":"Kafka on the Shore"
|
||||
},
|
||||
{
|
||||
"author":"Charles Bukowski",
|
||||
"category":"Fiction",
|
||||
"date":"2004-07-08",
|
||||
"isbn":"1852272007",
|
||||
"price":22.48,
|
||||
"ratings":
|
||||
{
|
||||
"*****":4
|
||||
},
|
||||
"title":"Pulp"
|
||||
},
|
||||
{
|
||||
"author":"Haruki Murakami",
|
||||
"category":"Fiction",
|
||||
"date":"2002-04-09",
|
||||
"isbn":"037571894X",
|
||||
"price":9.01,
|
||||
"title":"A Wild Sheep Chase: A Novel"
|
||||
},
|
||||
{
|
||||
"author":"George Crile",
|
||||
"category":"History",
|
||||
"date":"2007-11-06",
|
||||
"isbn":"0802143415",
|
||||
"price":10.5,
|
||||
"title":"Charlie Wilson's War"
|
||||
}
|
||||
]
|
||||
```
|
||||
### json query
|
||||
|
||||
```c++
|
||||
#include <fstream>
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons_ext/jsonpath/json_query.hpp>
|
||||
|
||||
// For convenience
|
||||
using jsoncons::json;
|
||||
using jsoncons::jsonpath::json_query;
|
||||
|
||||
// Deserialize the booklist
|
||||
std::ifstream is("booklist.json");
|
||||
json booklist;
|
||||
is >> booklist;
|
||||
|
||||
// Use a JSONPath expression to find
|
||||
//
|
||||
// (1) The authors of books that cost less than $12
|
||||
json result = json_query(booklist, "$[*][?(@.price < 12)].author");
|
||||
std::cout << result << std::endl;
|
||||
|
||||
// (2) The number of books
|
||||
result = json_query(booklist, "$.length");
|
||||
std::cout << result << std::endl;
|
||||
|
||||
// (3) The third book
|
||||
result = json_query(booklist, "$[2]");
|
||||
std::cout << std::endl << pretty_print(result) << std::endl;
|
||||
|
||||
// (4) The authors of books that were published in 2004
|
||||
result = json_query(booklist, "$[*][?(@.date =~ /2004.*?/)].author");
|
||||
std::cout << result << std::endl;
|
||||
|
||||
// (5) The titles of all books that have ratings
|
||||
result = json_query(booklist, "$[*][?(@.ratings)].title");
|
||||
std::cout << result << std::endl;
|
||||
|
||||
// (6) All authors and titles of books
|
||||
result = json_query(booklist, "$..['author','title']");
|
||||
std::cout << pretty_print(result) << std::endl;
|
||||
```
|
||||
Result:
|
||||
```json
|
||||
(1) ["Haruki Murakami","George Crile"]
|
||||
(2) [4]
|
||||
(3)
|
||||
[
|
||||
{
|
||||
"author":"Haruki Murakami",
|
||||
"category":"Fiction",
|
||||
"date":"2002-04-09",
|
||||
"isbn":"037571894X",
|
||||
"price":9.01,
|
||||
"title":"A Wild Sheep Chase: A Novel"
|
||||
}
|
||||
]
|
||||
(4) ["Charles Bukowski"]
|
||||
(5) ["Pulp"]
|
||||
(6)
|
||||
[
|
||||
"Nigel Rees",
|
||||
"Sayings of the Century",
|
||||
"Evelyn Waugh",
|
||||
"Sword of Honour",
|
||||
"Herman Melville",
|
||||
"Moby Dick",
|
||||
"J. R. R. Tolkien",
|
||||
"The Lord of the Rings"
|
||||
]
|
||||
```
|
||||
## Once again, this time with wide characters
|
||||
|
||||
### wjson construction
|
||||
|
||||
```c++
|
||||
#include <jsoncons/json.hpp>
|
||||
|
||||
// For convenience
|
||||
using jsoncons::wjson;
|
||||
|
||||
// Construct a book object
|
||||
wjson book1;
|
||||
|
||||
book1[L"category"] = L"Fiction";
|
||||
book1[L"title"] = L"A Wild Sheep Chase: A Novel";
|
||||
book1[L"author"] = L"Haruki Murakami";
|
||||
book1[L"date"] = L"2002-04-09";
|
||||
book1[L"price"] = 9.01;
|
||||
book1[L"isbn"] = L"037571894X";
|
||||
|
||||
// Construct another using the insert_or_assign function
|
||||
wjson book2;
|
||||
|
||||
book2.insert_or_assign(L"category", L"History");
|
||||
book2.insert_or_assign(L"title", L"Charlie Wilson's War");
|
||||
book2.insert_or_assign(L"author", L"George Crile");
|
||||
book2.insert_or_assign(L"date", L"2007-11-06");
|
||||
book2.insert_or_assign(L"price", 10.50);
|
||||
book2.insert_or_assign(L"isbn", L"0802143415");
|
||||
|
||||
// Use insert_or_assign again, but more efficiently
|
||||
wjson book3;
|
||||
|
||||
// Reserve memory, to avoid reallocations
|
||||
book3.reserve(6);
|
||||
|
||||
// Insert in name alphabetical order
|
||||
// Give insert_or_assign a hint where to insert the next member
|
||||
auto hint = book3.insert_or_assign(book3.object_range().begin(), L"author", L"Haruki Murakami");
|
||||
hint = book3.insert_or_assign(hint, L"category", L"Fiction");
|
||||
hint = book3.insert_or_assign(hint, L"date", L"2006-01-03");
|
||||
hint = book3.insert_or_assign(hint, L"isbn", L"1400079276");
|
||||
hint = book3.insert_or_assign(hint, L"price", 13.45);
|
||||
hint = book3.insert_or_assign(hint, L"title", L"Kafka on the Shore");
|
||||
|
||||
// Construct a fourth from a string
|
||||
wjson book4 = wjson::parse(LR"(
|
||||
{
|
||||
"category" : "Fiction",
|
||||
"title" : "Pulp",
|
||||
"author" : "Charles Bukowski",
|
||||
"date" : "2004-07-08",
|
||||
"price" : 22.48,
|
||||
"isbn" : "1852272007"
|
||||
}
|
||||
)");
|
||||
|
||||
// Construct a booklist array
|
||||
|
||||
wjson booklist = wjson::array();
|
||||
|
||||
// For efficiency, reserve memory, to avoid reallocations
|
||||
booklist.reserve(4);
|
||||
|
||||
// For efficency, tell jsoncons to move the contents
|
||||
// of the four book objects into the array
|
||||
booklist.add(std::move(book1));
|
||||
booklist.add(std::move(book2));
|
||||
|
||||
// Add the third book to the front
|
||||
auto pos = booklist.add(booklist.array_range().begin(),std::move(book3));
|
||||
|
||||
// and the last one immediately after
|
||||
booklist.add(pos+1,std::move(book4));
|
||||
|
||||
// See what's left of book1, 2, 3 and 4 (expect nulls)
|
||||
std::wcout << book1 << L"," << book2 << L"," << book3 << L"," << book4 << std::endl;
|
||||
|
||||
++
|
||||
//Loop through the booklist elements using a range-based for loop
|
||||
for (const auto& book : booklist.array_range())
|
||||
{
|
||||
std::wcout << book[L"title"].as<std::wstring>()
|
||||
<< L","
|
||||
<< book[L"price"].as<double>() << std::endl;
|
||||
}
|
||||
|
||||
// The second book
|
||||
wjson& book = booklist[1];
|
||||
|
||||
//Loop through the book's name-value pairs using a range-based for loop
|
||||
for (const auto& member : book.object_range())
|
||||
{
|
||||
std::wcout << member.key()
|
||||
<< L","
|
||||
<< member.value() << std::endl;
|
||||
}
|
||||
|
||||
auto it = book.find(L"author");
|
||||
if (it != book.object_range().end())
|
||||
{
|
||||
// member "author" found
|
||||
}
|
||||
|
||||
if (book.contains(L"author"))
|
||||
{
|
||||
// book has a member "author"
|
||||
}
|
||||
|
||||
book.get(L"author", L"author unknown").as<std::wstring>();
|
||||
// Returns author if found, otherwise "author unknown"
|
||||
|
||||
try
|
||||
{
|
||||
book[L"ratings"].as<std::wstring>();
|
||||
}
|
||||
catch (const std::out_of_range& e)
|
||||
{
|
||||
// member "ratings" not found
|
||||
}
|
||||
|
||||
// Add ratings
|
||||
book[L"ratings"][L"*****"] = 4;
|
||||
book[L"ratings"][L"*"] = 2;
|
||||
|
||||
// Delete one-star ratings
|
||||
book[L"ratings"].erase(L"*");
|
||||
|
||||
```
|
||||
```c++
|
||||
// Serialize the booklist to a file
|
||||
std::wofstream os("booklist2.json");
|
||||
os << pretty_print(booklist);
|
||||
```
|
||||
### wjson query
|
||||
|
||||
```c++
|
||||
// Deserialize the booklist
|
||||
std::wifstream is("booklist2.json");
|
||||
wjson booklist;
|
||||
is >> booklist;
|
||||
|
||||
// Use a JSONPath expression to find
|
||||
//
|
||||
// (1) The authors of books that cost less than $12
|
||||
wjson result = json_query(booklist, L"$[*][?(@.price < 12)].author");
|
||||
std::wcout << result << std::endl;
|
||||
|
||||
// (2) The number of books
|
||||
result = json_query(booklist, L"$.length");
|
||||
std::wcout << result << std::endl;
|
||||
|
||||
// (3) The third book
|
||||
result = json_query(booklist, L"$[2]");
|
||||
std::wcout << pretty_print(result) << std::endl;
|
||||
|
||||
// (4) The authors of books that were published in 2004
|
||||
result = json_query(booklist, L"$[*][?(@.date =~ /2004.*?/)].author");
|
||||
std::wcout << result << std::endl;
|
||||
|
||||
// (5) The titles of all books that have ratings
|
||||
result = json_query(booklist, L"$[*][?(@.ratings)].title");
|
||||
std::wcout << result << std::endl;
|
||||
|
||||
// (6) All authors and titles of books
|
||||
result = json_query(booklist, L"$..['author','title']");
|
||||
std::wcout << pretty_print(result) << std::endl;
|
||||
```
|
||||
Result:
|
||||
```json
|
||||
(1) ["Haruki Murakami","George Crile"]
|
||||
(2) [4]
|
||||
(3)
|
||||
[
|
||||
{
|
||||
"author":"Haruki Murakami",
|
||||
"category":"Fiction",
|
||||
"date":"2002-04-09",
|
||||
"isbn":"037571894X",
|
||||
"price":9.01,
|
||||
"title":"A Wild Sheep Chase: A Novel"
|
||||
}
|
||||
]
|
||||
(4) ["Charles Bukowski"]
|
||||
(5) ["Pulp"]
|
||||
(6)
|
||||
[
|
||||
"Nigel Rees",
|
||||
"Sayings of the Century",
|
||||
"Evelyn Waugh",
|
||||
"Sword of Honour",
|
||||
"Herman Melville",
|
||||
"Moby Dick",
|
||||
"J. R. R. Tolkien",
|
||||
"The Lord of the Rings"
|
||||
]
|
||||
```
|
||||
|
|
@ -1,156 +0,0 @@
|
|||
## Examples
|
||||
|
||||
### Using `json` with boost stateless `fast_pool_allocator`
|
||||
```c++
|
||||
#include <boost/pool/pool_alloc.hpp>
|
||||
#include "jsoncons/json.hpp"
|
||||
|
||||
typedef jsoncons::basic_json<char, boost::fast_pool_allocator<void>> bfp_json;
|
||||
|
||||
bfp_json j;
|
||||
|
||||
j.insert_or_assign("FirstName","Joe");
|
||||
j.insert_or_assign("LastName","Smith");
|
||||
```
|
||||
|
||||
### Using `json` with stateful Boost.Interprocess allocators
|
||||
|
||||
```c++
|
||||
#include <boost/interprocess/managed_shared_memory.hpp>
|
||||
#include <boost/interprocess/containers/vector.hpp>
|
||||
#include <boost/interprocess/allocators/allocator.hpp>
|
||||
#include <boost/interprocess/containers/string.hpp>
|
||||
#include <cstdlib> //std::system
|
||||
#include <jsoncons/json.hpp>
|
||||
|
||||
using namespace jsoncons;
|
||||
|
||||
typedef boost::interprocess::allocator<int,
|
||||
boost::interprocess::managed_shared_memory::segment_manager> shmem_allocator;
|
||||
|
||||
struct boost_sorted_policy : public sorted_policy
|
||||
{
|
||||
template <class T, class Allocator>
|
||||
using sequence_container_type = boost::interprocess::vector<T,Allocator>;
|
||||
|
||||
template <class CharT, class CharTraits, class Allocator>
|
||||
using key_storage = boost::interprocess::basic_string<CharT, CharTraits, Allocator>;
|
||||
|
||||
template <class CharT, class CharTraits, class Allocator>
|
||||
using string_storage = boost::interprocess::basic_string<CharT, CharTraits, Allocator>;
|
||||
};
|
||||
|
||||
typedef basic_json<char,boost_sorted_policy,shmem_allocator> shm_json;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
typedef std::pair<double, int> MyType;
|
||||
|
||||
if(argc == 1){ //Parent process
|
||||
//Remove shared memory on construction and destruction
|
||||
struct shm_remove
|
||||
{
|
||||
shm_remove() { boost::interprocess::shared_memory_object::remove("MySharedMemory"); }
|
||||
~shm_remove(){ boost::interprocess::shared_memory_object::remove("MySharedMemory"); }
|
||||
} remover;
|
||||
|
||||
//Construct managed shared memory
|
||||
boost::interprocess::managed_shared_memory segment(boost::interprocess::create_only,
|
||||
"MySharedMemory", 65536);
|
||||
|
||||
//Initialize shared memory STL-compatible allocator
|
||||
const shmem_allocator allocator(segment.get_segment_manager());
|
||||
|
||||
// Create json value with all dynamic allocations in shared memory
|
||||
|
||||
shm_json* j = segment.construct<shm_json>("my json")(shm_json::array(allocator));
|
||||
j->push_back(10);
|
||||
|
||||
shm_json o(allocator);
|
||||
o.insert_or_assign("category", "reference");
|
||||
o.insert_or_assign("author", "Nigel Rees");
|
||||
o.insert_or_assign("title", "Sayings of the Century");
|
||||
o.insert_or_assign("price", 8.95);
|
||||
|
||||
j->push_back(o);
|
||||
|
||||
shm_json a = shm_json::array(2,shm_json::object(allocator),allocator);
|
||||
a[0]["first"] = 1;
|
||||
|
||||
j->push_back(a);
|
||||
|
||||
std::pair<shm_json*, boost::interprocess::managed_shared_memory::size_type> res;
|
||||
res = segment.find<shm_json>("my json");
|
||||
|
||||
std::cout << "Parent:" << std::endl;
|
||||
std::cout << pretty_print(*(res.first)) << std::endl;
|
||||
|
||||
//Launch child process
|
||||
std::string s(argv[0]); s += " child ";
|
||||
if(0 != std::system(s.c_str()))
|
||||
return 1;
|
||||
|
||||
|
||||
//Check child has destroyed all objects
|
||||
if(segment.find<MyType>("my json").first)
|
||||
return 1;
|
||||
}
|
||||
else{
|
||||
//Open managed shared memory
|
||||
boost::interprocess::managed_shared_memory segment(boost::interprocess::open_only,
|
||||
"MySharedMemory");
|
||||
|
||||
std::pair<shm_json*, boost::interprocess::managed_shared_memory::size_type> res;
|
||||
res = segment.find<shm_json>("my json");
|
||||
|
||||
if (res.first != nullptr)
|
||||
{
|
||||
std::cout << "Child:" << std::endl;
|
||||
std::cout << pretty_print(*(res.first)) << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Result is null" << std::endl;
|
||||
}
|
||||
|
||||
//We're done, delete all the objects
|
||||
segment.destroy<shm_json>("my json");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```
|
||||
Parent:
|
||||
[
|
||||
10,
|
||||
{
|
||||
"author": "Nigel Rees",
|
||||
"category": "reference",
|
||||
"price": 8.95,
|
||||
"title": "Sayings of the Century"
|
||||
},
|
||||
[
|
||||
{
|
||||
"first": 1
|
||||
},
|
||||
{}
|
||||
]
|
||||
]
|
||||
Child:
|
||||
[
|
||||
10,
|
||||
{
|
||||
"author": "Nigel Rees",
|
||||
"category": "reference",
|
||||
"price": 8.95,
|
||||
"title": "Sayings of the Century"
|
||||
},
|
||||
[
|
||||
{
|
||||
"first": 1
|
||||
},
|
||||
{}
|
||||
]
|
||||
]
|
||||
```
|
|
@ -1,182 +0,0 @@
|
|||
### Narrow character support for UTF8 encoding
|
||||
|
||||
In the Linux and web worlds, `UTF-8` is the dominant character encoding.
|
||||
|
||||
Note that (at least in MSVS) you cannot open a Windows file with a Unicode name using the standard
|
||||
```c++
|
||||
std::fstream fs(const char* filename)
|
||||
```
|
||||
Instead you need to use the non standard Microsoft extension
|
||||
```c++
|
||||
std::fstream fs(const wchar_t* filename)
|
||||
```
|
||||
|
||||
#### Unicode escaping
|
||||
```c++
|
||||
string inputStr("[\"\\u0040\\u0040\\u0000\\u0011\"]");
|
||||
std::cout << "Input: " << inputStr << std::endl;
|
||||
|
||||
json arr = json::parse(inputStr);
|
||||
std::string str = arr[0].as<std::string>();
|
||||
std::cout << "Hex dump: [";
|
||||
for (size_t i = 0; i < str.size(); ++i)
|
||||
{
|
||||
unsigned int val = static_cast<unsigned int>(str[i]);
|
||||
if (i != 0)
|
||||
{
|
||||
std::cout << " ";
|
||||
}
|
||||
std::cout << "0x" << std::setfill('0') << std::setw(2) << std::hex << val;
|
||||
}
|
||||
std::cout << "]" << std::endl;
|
||||
|
||||
std::ostringstream os;
|
||||
os << arr;
|
||||
std::cout << "Output: " << os.str() << std::endl;
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
Input: ["\u0040\u0040\u0000\u0011"]
|
||||
Hex dump: [0x40 0x40 0x00 0x11]
|
||||
Output: ["@@\u0000\u0011"]
|
||||
```
|
||||
Note that just the two control characters are escaped on output.
|
||||
|
||||
#### Reading escaped unicode into utf8 encodings and writing back escaped unicode
|
||||
```c++
|
||||
string inputStr("[\"\\u007F\\u07FF\\u0800\"]");
|
||||
std::cout << "Input: " << inputStr << std::endl;
|
||||
|
||||
json arr = json::parse(inputStr);
|
||||
std::string s = arr[0].as<string>();
|
||||
std::cout << "Hex dump: [";
|
||||
for (size_t i = 0; i < s.size(); ++i)
|
||||
{
|
||||
if (i != 0)
|
||||
std::cout << " ";
|
||||
unsigned int u(s[i] >= 0 ? s[i] : 256 + s[i] );
|
||||
std::cout << "0x" << std::hex<< std::setfill('0') << std::setw(2) << u;
|
||||
}
|
||||
std::cout << "]" << std::endl;
|
||||
|
||||
std::ostringstream os;
|
||||
json_options options;
|
||||
format.escape_all_non_ascii(true);
|
||||
os << print(arr,options);
|
||||
std::string outputStr = os.str();
|
||||
std::cout << "Output: " << os.str() << std::endl;
|
||||
|
||||
json arr2 = json::parse(outputStr);
|
||||
std::string s2 = arr2[0].as<string>();
|
||||
std::cout << "Hex dump: [";
|
||||
for (size_t i = 0; i < s2.size(); ++i)
|
||||
{
|
||||
if (i != 0)
|
||||
std::cout << " ";
|
||||
unsigned int u(s2[i] >= 0 ? s2[i] : 256 + s2[i] );
|
||||
std::cout << "0x" << std::hex<< std::setfill('0') << std::setw(2) << u;
|
||||
}
|
||||
std::cout << "]" << std::endl;
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
Input: ["\u007F\u07FF\u0800"]
|
||||
Hex dump: [0x7f 0xdf 0xbf 0xe0 0xa0 0x80]
|
||||
Output: ["\u007F\u07FF\u0800"]
|
||||
Hex dump: [0x7f 0xdf 0xbf 0xe0 0xa0 0x80]
|
||||
```
|
||||
Since the escaped unicode consists of a control character (0x7f) and non-ascii, we get back the same text as what we started with.
|
||||
|
||||
#### Reading escaped unicode into utf8 encodings and writing back escaped unicode (with continuations)
|
||||
```c++
|
||||
string input = "[\"\\u8A73\\u7D30\\u95B2\\u89A7\\uD800\\uDC01\\u4E00\"]";
|
||||
json value = json::parse(input);
|
||||
json_options options;
|
||||
format.escape_all_non_ascii(true);
|
||||
string output;
|
||||
value.dump(output,options);
|
||||
|
||||
std::cout << "Input:" << std::endl;
|
||||
std::cout << input << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << "Output:" << std::endl;
|
||||
std::cout << output << std::endl;
|
||||
```
|
||||
Since all of the escaped unicode is non-ascii, we get back the same text as what we started with.
|
||||
```
|
||||
Input:
|
||||
["\u8A73\u7D30\u95B2\u89A7\uD800\uDC01\u4E00"]
|
||||
|
||||
Output:
|
||||
["\u8A73\u7D30\u95B2\u89A7\uD800\uDC01\u4E00"]
|
||||
```
|
||||
### Wide character support for UTF16 and UTF32 encodings
|
||||
|
||||
jsoncons supports wide character strings and streams with `wjson` and `wjson_reader`. It assumes `UTF16` encoding if `wchar_t` has size 2 (Windows) and `UTF32` encoding if `wchar_t` has size 4.
|
||||
|
||||
It is necessary to deal with UTF-16 character encoding in the Windows world because of lack of UTF-8 support in the Windows system API.
|
||||
|
||||
Even if you choose to use wide character streams and strings to interact with the Windows API, you can still read and write to files in the more widely supported, endiness independent, UTF-8 format. To handle that you need to imbue your streams with the facet `std::codecvt_utf8_utf16`, which encapsulates the conversion between `UTF-8` and `UTF-16`.
|
||||
|
||||
Note that (at least in MSVS) you cannot open a Windows file with a Unicode name using the standard
|
||||
|
||||
std::wfstream fs(const char* filename)
|
||||
|
||||
Instead you need to use the non standard Microsoft extension
|
||||
|
||||
std::wfstream fs(const wchar_t* filename)
|
||||
|
||||
#### Constructing a wjson value
|
||||
```c++
|
||||
using jsoncons::wjson;
|
||||
|
||||
wjson root;
|
||||
root[L"field1"] = L"test";
|
||||
root[L"field2"] = 3.9;
|
||||
root[L"field3"] = true;
|
||||
std::wcout << root << L"\n";
|
||||
```
|
||||
Output:
|
||||
```
|
||||
{"field1":"test","field2":3.9,"field3":true}
|
||||
```
|
||||
#### Escaped unicode
|
||||
```c++
|
||||
wstring input = L"[\"\\u007F\\u07FF\\u0800\"]";
|
||||
std::wistringstream is(input);
|
||||
|
||||
wjson val = wjson::parse(is);
|
||||
|
||||
wstring s = val[0].as<wstring>();
|
||||
std::cout << "length=" << s.length() << std::endl;
|
||||
std::cout << "Hex dump: [";
|
||||
for (size_t i = 0; i < s.size(); ++i)
|
||||
{
|
||||
if (i != 0)
|
||||
std::cout << " ";
|
||||
uint32_t u(s[i] >= 0 ? s[i] : 256 + s[i] );
|
||||
std::cout << "0x" << std::hex<< std::setfill('0') << std::setw(2) << u;
|
||||
}
|
||||
std::cout << "]" << std::endl;
|
||||
|
||||
std::wofstream os("output/xxx.txt");
|
||||
os.imbue(std::locale(os.getloc(), new std::codecvt_utf8_utf16<wchar_t>));
|
||||
|
||||
wjson_options options;
|
||||
format.escape_all_non_ascii(true);
|
||||
|
||||
os << pretty_print(val,options) << L"\n";
|
||||
```
|
||||
Output:
|
||||
```
|
||||
length=3
|
||||
Hex dump: [0x7f 0x7ff 0x800]
|
||||
```
|
||||
and the file `xxx.txt` contains
|
||||
```
|
||||
["\u007F\u07FF\u0800"]
|
||||
```
|
|
@ -1,6 +0,0 @@
|
|||
Start Visual Studio Command prompt for x64
|
||||
|
||||
mkdir build64 & pushd build64
|
||||
cmake -G "Visual Studio 14 2015 Win64" ..
|
||||
popd
|
||||
cmake --build build64 --config Debug
|
|
@ -1,101 +0,0 @@
|
|||
### jsoncons::bigint_chars_format
|
||||
|
||||
```c++
|
||||
enum class bigint_chars_format : uint8_t {number, base10, base64, base64url};
|
||||
```
|
||||
|
||||
#### Header
|
||||
```c++
|
||||
#include <jsoncons/json_options.hpp>
|
||||
```
|
||||
|
||||
Specifies `bignum` formatting.
|
||||
|
||||
### Examples
|
||||
|
||||
#### Initializing with bignum
|
||||
|
||||
```c++
|
||||
#include <jsoncons/json.hpp>
|
||||
|
||||
using namespace jsoncons;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::string s = "-18446744073709551617";
|
||||
|
||||
json j(bignum(s.c_str()));
|
||||
|
||||
std::cout << "(default) ";
|
||||
j.dump(std::cout);
|
||||
std::cout << "\n\n";
|
||||
|
||||
std::cout << "(integer) ";
|
||||
json_options options1;
|
||||
options1.bigint_format(bigint_chars_format::number);
|
||||
j.dump(std::cout, options1);
|
||||
std::cout << "\n\n";
|
||||
|
||||
std::cout << "(base64) ";
|
||||
json_options options3;
|
||||
options3.bigint_format(bigint_chars_format::base64);
|
||||
j.dump(std::cout, options3);
|
||||
std::cout << "\n\n";
|
||||
|
||||
std::cout << "(base64url) ";
|
||||
json_options options4;
|
||||
options4.bigint_format(bigint_chars_format::base64url);
|
||||
j.dump(std::cout, options4);
|
||||
std::cout << "\n\n";
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```
|
||||
(default) "-18446744073709551617"
|
||||
|
||||
(integer) -18446744073709551617
|
||||
|
||||
(base64) "~AQAAAAAAAAAA"
|
||||
|
||||
(base64url) "~AQAAAAAAAAAA"
|
||||
```
|
||||
|
||||
#### Integer overflow during parsing
|
||||
|
||||
```c++
|
||||
#include <jsoncons/json.hpp>
|
||||
|
||||
using namespace jsoncons;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::string s = "-18446744073709551617";
|
||||
|
||||
json j = json::parse(s);
|
||||
|
||||
std::cout << "(1) ";
|
||||
j.dump(std::cout);
|
||||
std::cout << "\n\n";
|
||||
|
||||
std::cout << "(2) ";
|
||||
json_options options1;
|
||||
options1.bigint_format(bigint_chars_format::number);
|
||||
j.dump(std::cout, options1);
|
||||
std::cout << "\n\n";
|
||||
|
||||
std::cout << "(3) ";
|
||||
json_options options2;
|
||||
options2.bigint_format(bigint_chars_format::base64url);
|
||||
j.dump(std::cout, options2);
|
||||
std::cout << "\n\n";
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```
|
||||
(1) "-18446744073709551617"
|
||||
|
||||
(2) -18446744073709551617
|
||||
|
||||
(3) "~AQAAAAAAAAAB"
|
||||
```
|
||||
|
|
@ -1,279 +0,0 @@
|
|||
### jsoncons::bignum
|
||||
|
||||
```c++
|
||||
typedef basic_bignum<Allocator = std::allocator<uint8_t>> bignum;
|
||||
```
|
||||
The `bignum` class is an instantiation of the `basic_bignum` class template that uses `std::allocator<uint8_t>` as the allocator type.
|
||||
|
||||
An arbitrary-precision integer.
|
||||
|
||||
#### Header
|
||||
```c++
|
||||
#include <jsoncons/bignum.hpp>
|
||||
```
|
||||
|
||||
#### Constructor
|
||||
|
||||
bignum();
|
||||
|
||||
explicit bignum(const Allocator& alloc);
|
||||
|
||||
explicit bignum(const char* str);
|
||||
Constructs a bignum from the decimal string representation of a bignum.
|
||||
|
||||
explicit bignum(const char* data, size_t length);
|
||||
Constructs a bignum from the decimal string representation of a bignum.
|
||||
|
||||
explicit bignum(const char* str, const Allocator& alloc);
|
||||
|
||||
bignum(int signum, std::initializer_list<uint8_t> magnitude);
|
||||
Constructs a bignum from the sign-magnitude representation.
|
||||
The magnitude is an unsigned integer `n` encoded as a byte string data item in big-endian byte-order.
|
||||
If the value of signum is 1, the value of the bignum is `n`.
|
||||
If the value of signum is -1, the value of the bignum is `-1 - n`.
|
||||
An empty list means a zero value.
|
||||
|
||||
bignum(int signum, std::initializer_list<uint8_t> magnitude, const Allocator& alloc);
|
||||
|
||||
bignum(const bignum& s);
|
||||
|
||||
bignum(bignum&& s);
|
||||
|
||||
#### Assignment
|
||||
|
||||
bignum& operator=(const bignum& s);
|
||||
|
||||
bignum& operator=(bignum&& s);
|
||||
|
||||
#### Accessors
|
||||
|
||||
template <typename Ch, typename Traits, typename Alloc>
|
||||
void dump(std::basic_string<Ch,Traits,Alloc>& data) const
|
||||
|
||||
template <typename Alloc>
|
||||
void dump(int& signum, std::vector<uint8_t,Alloc>& data) const
|
||||
|
||||
#### Arithmetic operators
|
||||
|
||||
explicit operator bool() const
|
||||
|
||||
explicit operator int64_t() const
|
||||
|
||||
explicit operator uint64_t() const
|
||||
|
||||
explicit operator double() const
|
||||
|
||||
explicit operator long double() const
|
||||
|
||||
bignum operator-() const
|
||||
|
||||
bignum& operator+=( const bignum& y )
|
||||
|
||||
bignum& operator-=( const bignum& y )
|
||||
|
||||
bignum& operator*=( int64_t y )
|
||||
|
||||
bignum& operator*=( uint64_t y )
|
||||
|
||||
bignum& operator*=( bignum y )
|
||||
|
||||
bignum& operator/=( const bignum& divisor )
|
||||
|
||||
bignum& operator%=( const bignum& divisor )
|
||||
|
||||
bignum& operator<<=( uint64_t k )
|
||||
|
||||
bignum& operator>>=(uint64_t k)
|
||||
|
||||
bignum& operator++()
|
||||
|
||||
bignum operator++(int)
|
||||
|
||||
bignum& operator--()
|
||||
|
||||
bignum operator--(int)
|
||||
|
||||
bignum& operator|=( const bignum& a )
|
||||
|
||||
bignum& operator^=( const bignum& a )
|
||||
|
||||
bignum& operator&=( const bignum& a )
|
||||
|
||||
#### Non-member functions
|
||||
|
||||
bool operator==(const bignum& lhs, const bignum& rhs);
|
||||
|
||||
bool operator!=(const bignum& lhs, const bignum& rhs);
|
||||
|
||||
template <class CharT>
|
||||
friend std::basic_ostream<CharT>& operator<<(std::basic_ostream<CharT>& os, const bignum& o);
|
||||
|
||||
#### Global arithmetic operators
|
||||
|
||||
bool operator==( const bignum& x, const bignum& y )
|
||||
|
||||
bool operator==( const bignum& x, int y )
|
||||
|
||||
bool operator!=( const bignum& x, const bignum& y )
|
||||
|
||||
bool operator!=( const bignum& x, int y )
|
||||
|
||||
bool operator<( const bignum& x, const bignum& y )
|
||||
|
||||
bool operator<( const bignum& x, int64_t y )
|
||||
|
||||
bool operator>( const bignum& x, const bignum& y )
|
||||
|
||||
bool operator>( const bignum& x, int y )
|
||||
|
||||
bool operator<=( const bignum& x, const bignum& y )
|
||||
|
||||
bool operator<=( const bignum& x, int y )
|
||||
|
||||
bool operator>=( const bignum& x, const bignum& y )
|
||||
|
||||
bool operator>=( const bignum& x, int y )
|
||||
|
||||
bignum operator+( bignum x, const bignum& y )
|
||||
|
||||
bignum operator+( bignum x, int64_t y )
|
||||
|
||||
bignum operator-( bignum x, const bignum& y )
|
||||
|
||||
bignum operator-( bignum x, int64_t y )
|
||||
|
||||
bignum operator*( int64_t x, const bignum& y )
|
||||
|
||||
bignum operator*( bignum x, const bignum& y )
|
||||
|
||||
bignum operator*( bignum x, int64_t y )
|
||||
|
||||
bignum operator/( bignum x, const bignum& y )
|
||||
|
||||
bignum operator/( bignum x, int y )
|
||||
|
||||
bignum operator%( bignum x, const bignum& y )
|
||||
|
||||
bignum operator<<( bignum u, unsigned k )
|
||||
|
||||
bignum operator<<( bignum u, int k )
|
||||
|
||||
bignum operator>>( bignum u, unsigned k )
|
||||
|
||||
bignum operator>>( bignum u, int k )
|
||||
|
||||
bignum operator|( bignum x, const bignum& y )
|
||||
|
||||
bignum operator|( bignum x, int y )
|
||||
|
||||
bignum operator|( bignum x, unsigned y )
|
||||
|
||||
bignum operator^( bignum x, const bignum& y )
|
||||
|
||||
bignum operator^( bignum x, int y )
|
||||
|
||||
bignum operator^( bignum x, unsigned y )
|
||||
|
||||
bignum operator&( bignum x, const bignum& y )
|
||||
|
||||
bignum operator&( bignum x, int y )
|
||||
|
||||
bignum operator&( bignum x, unsigned y )
|
||||
|
||||
bignum abs( const bignum& a )
|
||||
|
||||
bignum power( bignum x, unsigned n )
|
||||
|
||||
bignum sqrt( const bignum& a )
|
||||
|
||||
### Examples
|
||||
|
||||
|
||||
### Examples
|
||||
|
||||
#### Initializing with bignum
|
||||
|
||||
```c++
|
||||
#include <jsoncons/json.hpp>
|
||||
|
||||
using namespace jsoncons;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::string s = "-18446744073709551617";
|
||||
|
||||
json j(bignum(s.c_str()));
|
||||
|
||||
std::cout << "(1) " << j.as<bignum>() << "\n\n";
|
||||
|
||||
std::cout << "(2) " << j.as<std::string>() << "\n\n";
|
||||
|
||||
std::cout << "(3) ";
|
||||
j.dump(std::cout);
|
||||
std::cout << "\n\n";
|
||||
|
||||
std::cout << "(4) ";
|
||||
json_options options1;
|
||||
options1.bigint_format(bigint_chars_format::number);
|
||||
j.dump(std::cout, options1);
|
||||
std::cout << "\n\n";
|
||||
|
||||
std::cout << "(5) ";
|
||||
json_options options2;
|
||||
options2.bigint_format(bigint_chars_format::base64url);
|
||||
j.dump(std::cout, options2);
|
||||
std::cout << "\n\n";
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```
|
||||
(1) -18446744073709551617
|
||||
|
||||
(2) -18446744073709551617
|
||||
|
||||
(3) "-18446744073709551617"
|
||||
|
||||
(4) -18446744073709551617
|
||||
|
||||
(5) "~AQAAAAAAAAAB"
|
||||
```
|
||||
|
||||
#### Integer overflow during parsing
|
||||
|
||||
```c++
|
||||
#include <jsoncons/json.hpp>
|
||||
|
||||
using namespace jsoncons;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::string s = "-18446744073709551617";
|
||||
|
||||
json j = json::parse(s);
|
||||
|
||||
std::cout << "(1) ";
|
||||
j.dump(std::cout);
|
||||
std::cout << "\n\n";
|
||||
|
||||
std::cout << "(2) ";
|
||||
json_options options1;
|
||||
options1.bigint_format(bigint_chars_format::number);
|
||||
j.dump(std::cout, options1);
|
||||
std::cout << "\n\n";
|
||||
|
||||
std::cout << "(3) ";
|
||||
json_options options2;
|
||||
options2.bigint_format(bigint_chars_format::base64url);
|
||||
j.dump(std::cout, options2);
|
||||
std::cout << "\n\n";
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```
|
||||
(1) "-18446744073709551617"
|
||||
|
||||
(2) -18446744073709551617
|
||||
|
||||
(3) "~AQAAAAAAAAAB"
|
||||
```
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
### bson extension
|
||||
|
||||
The bson extension implements decode from and encode to the [Binary JSON](http://bsonspec.org/) data format.
|
||||
You can either parse into or serialize from a variant-like structure, [basic_json](../json.md), or your own
|
||||
data structures, using [json_type_traits](../json_type_traits.md).
|
||||
|
||||
[decode_bson](decode_bson.md)
|
||||
|
||||
[encode_bson](encode_bson.md)
|
||||
|
||||
[bson_encoder](bson_encoder.md)
|
||||
|
||||
#### jsoncons-BSON mappings
|
||||
|
||||
jsoncons data item|jsoncons tag|BSON data item
|
||||
--------------|------------------|---------------
|
||||
null | | null
|
||||
bool | | true or false
|
||||
int64 | | int32 or int64
|
||||
int64 | timestamp | datetime
|
||||
uint64 | | int32 or int64
|
||||
uint64 | timestamp | datetime
|
||||
double | | double
|
||||
string | | string
|
||||
byte_string | | binary
|
||||
array | | 0x04 (array )
|
||||
object | | 0x03 (document)
|
||||
|
||||
|
|
@ -1,147 +0,0 @@
|
|||
### jsoncons::bson::basic_bson_encoder
|
||||
|
||||
```c++
|
||||
template<
|
||||
class Result>
|
||||
> class basic_bson_encoder : public jsoncons::json_content_handler
|
||||
```
|
||||
|
||||
`basic_bson_encoder` is noncopyable.
|
||||
|
||||
#### Header
|
||||
|
||||
#include <jsoncons_ext/bson/bson_encoder.hpp>
|
||||
|
||||
![bson_encoder](./diagrams/bson_encoder.png)
|
||||
|
||||
Two specializations for common result types are defined:
|
||||
|
||||
Type |Definition
|
||||
---------------------------|------------------------------
|
||||
bson_encoder |basic_bson_encoder<jsoncons::binary_stream_result>
|
||||
bson_bytes_encoder |basic_bson_encoder<jsoncons::binary_buffer_result>
|
||||
|
||||
#### Member types
|
||||
|
||||
Type |Definition
|
||||
---------------------------|------------------------------
|
||||
char_type |char
|
||||
result_type |Result
|
||||
string_view_type |
|
||||
|
||||
#### Constructors
|
||||
|
||||
explicit basic_bson_encoder(result_type result)
|
||||
Constructs a new encoder that writes to the specified result.
|
||||
|
||||
#### Destructor
|
||||
|
||||
virtual ~basic_bson_encoder()
|
||||
|
||||
### Inherited from [basic_json_content_handler](../json_content_handler.md)
|
||||
|
||||
#### Member functions
|
||||
|
||||
bool begin_object(semantic_tag tag=semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool begin_object(size_t length,
|
||||
semantic_tag tag=semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool end_object(const ser_context& context = null_ser_context())
|
||||
|
||||
bool begin_array(semantic_tag tag=semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool begin_array(semantic_tag tag=semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool end_array(const ser_context& context=null_ser_context());
|
||||
|
||||
bool name(const string_view_type& name,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool string_value(const string_view_type& value,
|
||||
semantic_tag tag = semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool byte_string_value(const byte_string_view& b,
|
||||
semantic_tag tag=semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool byte_string_value(const uint8_t* p, size_t size,
|
||||
semantic_tag tag=semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool int64_value(int64_t value,
|
||||
semantic_tag tag = semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool uint64_value(uint64_t value,
|
||||
semantic_tag tag = semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool double_value(double value,
|
||||
semantic_tag tag = semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool bool_value(bool value,
|
||||
semantic_tag tag = semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool null_value(semantic_tag tag = semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
void flush()
|
||||
|
||||
### Examples
|
||||
|
||||
#### Encode to BSON
|
||||
|
||||
```c++
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons_ext/bson/bson.hpp>
|
||||
#include <iomanip>
|
||||
|
||||
int main()
|
||||
{
|
||||
std::vector<uint8_t> buffer;
|
||||
bson::bson_bytes_encoder encoder(buffer);
|
||||
encoder.begin_array(); // The total number of bytes comprising
|
||||
// the bson document will be calculated
|
||||
encoder.string_value("cat");
|
||||
encoder.byte_string_value(byte_string({'p','u','r','r'}));
|
||||
encoder.int64_value(1431027667, semantic_tag::timestamp);
|
||||
encoder.end_array();
|
||||
encoder.flush();
|
||||
|
||||
for (auto c : buffer)
|
||||
{
|
||||
std::cout << std::hex << std::setprecision(2) << std::setw(2)
|
||||
<< std::noshowbase << std::setfill('0') << static_cast<int>(c);
|
||||
}
|
||||
std::cout << "\n\n";
|
||||
|
||||
/*
|
||||
22000000 -- Total number of bytes comprising the document (34 bytes)
|
||||
02 -- UTF-8 string
|
||||
3000 -- "0"
|
||||
04000000 -- number bytes in the string (including trailing byte)
|
||||
636174 -- "cat"
|
||||
00 -- trailing byte
|
||||
05 -- binary
|
||||
3100 -- "1"
|
||||
04000000 -- number of bytes
|
||||
70757272 -- 'P''u''r''r'
|
||||
09 -- datetime
|
||||
3200 -- "2"
|
||||
d3bf4b55 -- 1431027667
|
||||
00
|
||||
*/
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```
|
||||
2200000002300004000000636174000531000400000070757272093200d3bf4b5500
|
||||
```
|
|
@ -1,30 +0,0 @@
|
|||
### jsoncons::bson::decode_bson
|
||||
|
||||
Decodes a [Binary JSON (BSON)](http://bsonspec.org/) data format into a C++ data structure.
|
||||
|
||||
#### Header
|
||||
```c++
|
||||
#include <jsoncons_ext/bson/bson.hpp>
|
||||
|
||||
template<class T>
|
||||
T decode_bson(const std::vector<uint8_t>& v); // (1)
|
||||
|
||||
template<class T>
|
||||
T decode_bson(std::istream& is); // (2)
|
||||
```
|
||||
|
||||
(1) Reads a BSON bytes buffer into a type T if T is an instantiation of [basic_json](../json.md)
|
||||
or if T supports [json_type_traits](../json_type_traits.md).
|
||||
|
||||
(2) Reads a BSON binary stream into a type T if T is an instantiation of [basic_json](../json.md)
|
||||
or if T supports [json_type_traits](../json_type_traits.md).
|
||||
|
||||
#### Exceptions
|
||||
|
||||
Throws [ser_error](../ser_error.md) if parsing fails.
|
||||
|
||||
#### See also
|
||||
|
||||
- [encode_bson](encode_bson.md) encodes a json value to the [Binary JSON](http://bsonspec.org/) data format.
|
||||
|
||||
|
Before Width: | Height: | Size: 5.1 KiB |
|
@ -1 +0,0 @@
|
|||
<mxfile modified="2019-03-29T03:25:17.280Z" host="www.draw.io" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36" etag="yA61vU4hp_5DYHRenpc1" version="10.5.9" type="device"><diagram id="iK-0d-7Yl-5MlnfMu26I" name="Page-1">vVZdb9owFP01eexEYqD0sQXabajVOiZBn5CJbxNvjs0cA2G/fjaxSZwElUpV+1D5nuvrj3POdQjQOCseJN6kj4IAC6IeKQI0CaLoOhzp/wY4lAAa9kogkZSUUFgBc/oPLOimbSmB3JuohGCKbnwwFpxDrDwMSyn2/rRXwfxdNziBFjCPMWujC0pUWqKjQa/CvwJNUrdz2LOZDLvJFshTTMS+BqFpgMZSCFWOsmIMzHDneCnr7s9kTweTwNUlBdOnXwWfPc/TaPx3phaP2Uvx/cqussNsay+8xjmNV79zwVeaU6UXX6WYEwYyiIZM73S3NqPEjLqQ41XVwfEnxZYTMEfo6fQ+pQrmGxyb7F4bRmOpypiOwlN1/UrufCAVFDXIXvEBRAZKHvQUmx1Ztq3dQsf+vhIvdBZMa8L1LYatX5LTyhWlemBZfQfD12cYXhuGgce6YT6B2VfK2FgwIY+1CI5/Gs+VFH+glkFDdIPIx2hxkRj9zxRj1BKjRStwcmveDR3FDOdaKp9JKKhaWtLN+MWMvwxsNClqqcnBBVwffukWMEGtyoRV2TFydWc1yMVWxvC26xSWCai3+x+I9wq2Fa0pNugQzGESGFZ057+dXSraHX4Iqm92Mkzf90uEGj4or22L6k9dY52bhu9GjXVKWlrrHC11uvRFLkt2j2k0e1rin5BcLZ5nsJtBR8t/4ylIqjDXoulvIcWJxFnLerqtlG82vz254NDoZQthRhNuHKuNop8TdGealOqv2K1NZJQQs03nO+G/JB/Q+GFDgKjX0fiow0fR+xtfh9U3tFSw+iGCpv8B</diagram></mxfile>
|
|
@ -1,25 +0,0 @@
|
|||
### jsoncons::bson::encode_bson
|
||||
|
||||
Encodes a C++ data structure to the [Binary JSON (BSON)](http://bsonspec.org/) data format.
|
||||
|
||||
#### Header
|
||||
```c++
|
||||
#include <jsoncons_ext/bson/bson.hpp>
|
||||
|
||||
template<class T>
|
||||
void encode_bson(const T& jval, std::vector<uint8_t>& v); // (1)
|
||||
|
||||
template<class T>
|
||||
void encode_bson(const T& jval, std::ostream& os); // (2)
|
||||
```
|
||||
|
||||
(1) Writes a value of type T into a bytes buffer in the BSON data format. Type T must be an instantiation of [basic_json](../json.md)
|
||||
or support [json_type_traits](../json_type_traits.md).
|
||||
|
||||
(2) Writes a value of type T into a binary stream in the BSON data format. Type T must be an instantiation of [basic_json](../json.md)
|
||||
or support [json_type_traits](../json_type_traits.md).
|
||||
|
||||
#### See also
|
||||
|
||||
- [decode_bson](decode_bson) decodes a [Binary JSON](http://bsonspec.org/) data format to a json value.
|
||||
|
|
@ -1,130 +0,0 @@
|
|||
### jsoncons::byte_string
|
||||
|
||||
```c++
|
||||
typedef basic_byte_string<Allocator = std::allocator<uint8_t>> byte_string;
|
||||
```
|
||||
The `byte_string` class is an instantiation of the `basic_byte_string` class template that uses `std::allocator<uint8_t>` as the allocator type.
|
||||
|
||||
#### Header
|
||||
```c++
|
||||
#include <jsoncons/byte_string.hpp>
|
||||
```
|
||||
|
||||
#### Member types
|
||||
|
||||
Member type |Definition
|
||||
------------------------------------|------------------------------
|
||||
`const_iterator`|
|
||||
`iterator`|Same as `const_iterator`
|
||||
`size_type`|std::size_t
|
||||
|
||||
#### Constructor
|
||||
|
||||
byte_string();
|
||||
|
||||
explicit byte_string(const Allocator& alloc);
|
||||
|
||||
byte_string(std::initializer_list<uint8_t> init);
|
||||
|
||||
byte_string(std::initializer_list<uint8_t> init, const Allocator& alloc);
|
||||
|
||||
explicit byte_string(const byte_string_view& v);
|
||||
|
||||
byte_string(const byte_string_view& v, const Allocator& alloc);
|
||||
|
||||
byte_string(const char* s);
|
||||
|
||||
byte_string(const byte_string& s);
|
||||
|
||||
byte_string(byte_string&& s);
|
||||
|
||||
#### Assignment
|
||||
|
||||
byte_string& operator=(const byte_string& s);
|
||||
|
||||
byte_string& operator=(byte_string&& s);
|
||||
|
||||
#### Iterators
|
||||
|
||||
const_iterator begin() const noexcept;
|
||||
|
||||
const_iterator end() const noexcept;
|
||||
|
||||
#### Element access
|
||||
|
||||
const uint8_t* data() const;
|
||||
|
||||
uint8_t operator[](size_type pos) const;
|
||||
|
||||
operator byte_string_view() const noexcept;
|
||||
|
||||
#### Capacity
|
||||
|
||||
size_t size() const;
|
||||
|
||||
size_t length() const;
|
||||
|
||||
#### Non-member functions
|
||||
|
||||
bool operator==(const byte_string& lhs, const byte_string& rhs);
|
||||
|
||||
bool operator!=(const byte_string& lhs, const byte_string& rhs);
|
||||
|
||||
template <class CharT>
|
||||
friend std::ostream& operator<<(std::ostream& os, const byte_string& o);
|
||||
|
||||
### Examples
|
||||
|
||||
#### Byte string from initializer list
|
||||
|
||||
```c++
|
||||
json j(byte_string({'H','e','l','l','o'}));
|
||||
byte_string bs = j.as<byte_string>();
|
||||
|
||||
std::cout << "(1) "<< bs << "\n\n";
|
||||
|
||||
std::cout << "(2) ";
|
||||
for (auto b : bs)
|
||||
{
|
||||
std::cout << (char)b;
|
||||
}
|
||||
std::cout << "\n\n";
|
||||
|
||||
std::cout << "(3) " << j << std::endl;
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
(1) 0x480x650x6c0x6c0x6f
|
||||
|
||||
(2) Hello
|
||||
|
||||
(3) "SGVsbG8_"
|
||||
```
|
||||
|
||||
#### Byte string from char array
|
||||
|
||||
```c++
|
||||
json j(byte_string("Hello"));
|
||||
byte_string bs = j.as<byte_string>();
|
||||
|
||||
std::cout << "(1) "<< bs << "\n\n";
|
||||
|
||||
std::cout << "(2) ";
|
||||
for (auto b : bs)
|
||||
{
|
||||
std::cout << (char)b;
|
||||
}
|
||||
std::cout << "\n\n";
|
||||
|
||||
std::cout << "(3) " << j << std::endl;
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
(1) 0x480x650x6c0x6c0x6f
|
||||
|
||||
(2) Hello
|
||||
|
||||
(3) "SGVsbG8_"
|
||||
```
|
|
@ -1,58 +0,0 @@
|
|||
### jsoncons::byte_string_chars_format
|
||||
|
||||
```c++
|
||||
enum class byte_string_chars_format : uint8_t {base16, base64, base64url};
|
||||
```
|
||||
|
||||
#### Header
|
||||
```c++
|
||||
#include <jsoncons/json_options.hpp>
|
||||
```
|
||||
|
||||
Specifies byte string formatting.
|
||||
|
||||
### Examples
|
||||
|
||||
#### Byte string formatting
|
||||
|
||||
```c++
|
||||
#include <jsoncons/json.hpp>
|
||||
|
||||
using namespace jsoncons;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::vector<uint8_t> bytes = {'H','e','l','l','o'};
|
||||
|
||||
json j(byte_string(bytes.data(),bytes.size()));
|
||||
|
||||
// default
|
||||
std::cout << "(1) "<< j << "\n\n";
|
||||
|
||||
// base16
|
||||
json_options options2;
|
||||
options2.byte_string_format(byte_string_chars_format::base16);
|
||||
std::cout << "(2) "<< print(j, options2) << "\n\n";
|
||||
|
||||
// base64
|
||||
json_options options3;
|
||||
options3.byte_string_format(byte_string_chars_format::base64);
|
||||
std::cout << "(3) "<< print(j, options3) << "\n\n";
|
||||
|
||||
// base64url
|
||||
json_options options4;
|
||||
options4.byte_string_format(byte_string_chars_format::base64url);
|
||||
std::cout << "(4) "<< print(j, options4) << "\n\n";
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```
|
||||
(1) "SGVsbG8"
|
||||
|
||||
(2) "48656C6C6F"
|
||||
|
||||
(3) "SGVsbG8="
|
||||
|
||||
(4) "SGVsbG8"
|
||||
```
|
||||
|
|
@ -1,175 +0,0 @@
|
|||
## cbor extension
|
||||
|
||||
The cbor extension implements decode from and encode to the IETF standard [Concise Binary Object Representation (CBOR)](http://cbor.io/).
|
||||
You can either parse into or serialize from a variant-like structure, [basic_json](../json.md), or your own
|
||||
data structures, using [json_type_traits](../json_type_traits.md).
|
||||
|
||||
[decode_cbor](decode_cbor.md)
|
||||
|
||||
[encode_cbor](encode_cbor.md)
|
||||
|
||||
[cbor_encoder](cbor_encoder.md)
|
||||
|
||||
[cbor_options](cbor_options.md)
|
||||
|
||||
### Tag handling and extensions
|
||||
|
||||
All tags not explicitly mentioned below are ignored.
|
||||
|
||||
0 (standard date/time string)
|
||||
CBOR standard date/time strings are decoded into jsoncons strings tagged with `semantic_tag::datetime`.
|
||||
jsoncons strings tagged with `semantic_tag::datetime` are encoded into CBOR standard date/time strings.
|
||||
|
||||
1 (epoch time)
|
||||
CBOR epoch times are decoded into jsoncons int64_t, uint64_t and double and tagged with `semantic_tag::timestamp`.
|
||||
jsoncons int64_t, uint64_t and double tagged with `semantic_tag::timestamp` are encoded into CBOR epoch time.
|
||||
|
||||
2,3 (positive and negative bignum)
|
||||
CBOR positive and negative bignums are decoded into jsoncons strings and tagged with `semantic_tag::bigint`.
|
||||
jsoncons strings tagged with `semantic_tag::bigint` are encoded into CBOR positive or negative bignums.
|
||||
|
||||
4 (decimal fratction)
|
||||
CBOR decimal fractions are decoded into jsoncons strings tagged with `semantic_tag::bigdec`.
|
||||
jsoncons strings tagged with `semantic_tag::bigdec` are encoded into CBOR decimal fractions.
|
||||
|
||||
5 (bigfloat)
|
||||
CBOR bigfloats are decoded into a jsoncons string that consists of the following parts
|
||||
|
||||
- (optional) minus sign
|
||||
- 0x
|
||||
- nonempty sequence of hexadecimal digits (defines mantissa)
|
||||
- p followed with optional minus or plus sign and nonempty sequence of hexadecimal digits (defines base-2 exponent)
|
||||
|
||||
and tagged with `semantic_tag::bigfloat`.
|
||||
|
||||
jsoncons strings that consist of the following parts
|
||||
|
||||
- (optional) plus or minus sign
|
||||
- 0x or 0X
|
||||
- nonempty sequence of hexadecimal digits optionally containing a decimal-point character
|
||||
- (optional) p or P followed with optional minus or plus sign and nonempty sequence of decimal digits
|
||||
|
||||
and tagged with `semantic_tag::bigfloat` are encoded into CBOR bignums.
|
||||
|
||||
21, 22, 23 (byte string expected conversion is base64url, base64 or base16)
|
||||
CBOR byte strings tagged with 21, 22 and 23 are decoded into jsoncons byte strings tagged with
|
||||
`semantic_tag::base64url`, `semantic_tag::base64` and `semantic_tag::base16`.
|
||||
jsoncons byte strings tagged with `semantic_tag::base64url`, `semantic_tag::base64` and `semantic_tag::base16`
|
||||
are encoded into CBOR byte strings tagged with 21, 22 and 23.
|
||||
|
||||
32 (URI)
|
||||
CBOR URI strings are decoded into jsoncons strings tagged with `semantic_tag::uri`.
|
||||
jsoncons strings tagged with `semantic_tag::uri` are encoded into CBOR URI strings.
|
||||
|
||||
33, 34 (UTF-8 string is base64url or base64)
|
||||
CBOR strings tagged with 33 and 34 are decoded into jsoncons strings tagged with `semantic_tag::base64url` and `semantic_tag::base64`.
|
||||
jsoncons strings tagged with `semantic_tag::base64url` and `semantic_tag::base64` are encoded into CBOR strings tagged with 33 and 34.
|
||||
|
||||
256, 25 [stringref-namespace, stringref](http://cbor.schmorp.de/stringref)
|
||||
Tags 256 and 25 are automatically decoded when detected. They are encoded when CBOR option `pack_strings` is set to true.
|
||||
|
||||
### jsoncons - CBOR mappings
|
||||
|
||||
jsoncons data item|jsoncons tag|CBOR data item|CBOR tag
|
||||
--------------|------------------|---------------|--------
|
||||
null | | null | 
|
||||
null | undefined | undefined | 
|
||||
bool | | true or false | 
|
||||
int64 | | unsigned or negative integer | 
|
||||
int64 | timestamp | unsigned or negative integer | 1 (epoch-based date/time)
|
||||
uint64 | | unsigned integer | 
|
||||
uint64 | timestamp | unsigned integer | 1 (epoch-based date/time)
|
||||
double | | half-precision float, float, or double | 
|
||||
double | timestamp | double | 1 (epoch-based date/time)
|
||||
string | | string | 
|
||||
string | bigint | byte string | 2 (positive bignum) or 2 (negative bignum)
|
||||
string | bigdec | array | 4 (decimal fraction)
|
||||
string | bigfloat | array | 5 (bigfloat)
|
||||
string | datetime | string | 0 (date/time string)
|
||||
string | uri | string | 32 (uri)
|
||||
string | base64url | string | 33 (base64url)
|
||||
string | base64 | string | 34 (base64)
|
||||
byte_string | | byte string | 
|
||||
byte_string | base64url | byte string | 21 (Expected conversion to base64url encoding)
|
||||
byte_string | base64 | byte string | 22 (Expected conversion to base64 encoding)
|
||||
byte_string | base16 | byte string | 23 (Expected conversion to base16 encoding)
|
||||
array | | array | 
|
||||
object | | map | 
|
||||
|
||||
### Examples
|
||||
|
||||
```c++
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons_ext/cbor/cbor.hpp>
|
||||
#include <jsoncons_ext/jsonpointer/jsonpointer.hpp>
|
||||
|
||||
using namespace jsoncons;
|
||||
|
||||
int main()
|
||||
{
|
||||
ojson j1 = ojson::parse(R"(
|
||||
{
|
||||
"application": "hiking",
|
||||
"reputons": [
|
||||
{
|
||||
"rater": "HikingAsylum.example.com",
|
||||
"assertion": "strong-hiker",
|
||||
"rated": "Marilyn C",
|
||||
"rating": 0.90
|
||||
}
|
||||
]
|
||||
}
|
||||
)");
|
||||
|
||||
// Encode a basic_json value to a CBOR value
|
||||
std::vector<uint8_t> data;
|
||||
cbor::encode_cbor(j1, data);
|
||||
|
||||
// Decode a CBOR value to a basic_json value
|
||||
ojson j2 = cbor::decode_cbor<ojson>(data);
|
||||
std::cout << "(1)\n" << pretty_print(j2) << "\n\n";
|
||||
|
||||
// Accessing the data items
|
||||
|
||||
const ojson& reputons = j2["reputons"];
|
||||
|
||||
std::cout << "(2)\n";
|
||||
for (auto element : reputons.array_range())
|
||||
{
|
||||
std::cout << element.at("rated").as<std::string>() << ", ";
|
||||
std::cout << element.at("rating").as<double>() << "\n";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
// Get a CBOR value for a nested data item with jsonpointer
|
||||
std::error_code ec;
|
||||
const auto& rated = jsonpointer::get(j2, "/reputons/0/rated", ec);
|
||||
if (!ec)
|
||||
{
|
||||
std::cout << "(3) " << rated.as_string() << "\n";
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```
|
||||
(1)
|
||||
{
|
||||
"application": "hiking",
|
||||
"reputons": [
|
||||
{
|
||||
"rater": "HikingAsylum.example.com",
|
||||
"assertion": "strong-hiker",
|
||||
"rated": "Marilyn C",
|
||||
"rating": 0.9
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
(2)
|
||||
Marilyn C, 0.9
|
||||
|
||||
(3) Marilyn C
|
||||
```
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
### jsoncons::cbor::cbor_decode_options
|
||||
|
||||
An abstract class that defines accessors for CBOR decoding options.
|
||||
|
||||
#### Header
|
||||
```c++
|
||||
#include <jsoncons/cbor/cbor_options.hpp>
|
||||
```
|
||||
|
||||
#### Implementing classes
|
||||
|
||||
[cbor_options](cbor_options.md)
|
||||
|
||||
#### Destructor
|
||||
|
||||
virtual ~cbor_decode_options();
|
||||
|
||||
#### Accessors
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
### jsoncons::cbor::cbor_encode_options
|
||||
|
||||
An abstract class that defines accessors for CBOR encoding options.
|
||||
|
||||
#### Header
|
||||
```c++
|
||||
#include <jsoncons/cbor/cbor_options.hpp>
|
||||
```
|
||||
|
||||
#### Implementing classes
|
||||
|
||||
[cbor_options](cbor_options.md)
|
||||
|
||||
#### Destructor
|
||||
|
||||
virtual ~cbor_encode_options();
|
||||
|
||||
#### Accessors
|
||||
|
||||
bool pack_strings() const;
|
|
@ -1,197 +0,0 @@
|
|||
### jsoncons::cbor::basic_cbor_encoder
|
||||
|
||||
```c++
|
||||
template<
|
||||
class Result>
|
||||
> class basic_cbor_encoder : public jsoncons::json_content_handler
|
||||
```
|
||||
|
||||
`basic_cbor_encoder` is noncopyable
|
||||
|
||||
#### Header
|
||||
|
||||
#include <jsoncons_ext/cbor/cbor_encoder.hpp>
|
||||
|
||||
![cbor_encoder](./diagrams/cbor_encoder.png)
|
||||
|
||||
Four specializations for common result types are defined:
|
||||
|
||||
Type |Definition
|
||||
---------------------------|------------------------------
|
||||
cbor_encoder |basic_cbor_encoder<jsoncons::binary_stream_result>
|
||||
cbor_bytes_encoder |basic_cbor_encoder<jsoncons::binary_buffer_result>
|
||||
|
||||
#### Member types
|
||||
|
||||
Type |Definition
|
||||
---------------------------|------------------------------
|
||||
char_type |char
|
||||
result_type |Result
|
||||
string_view_type |
|
||||
|
||||
#### Constructors
|
||||
|
||||
explicit basic_cbor_encoder(result_type result)
|
||||
Constructs a new encoder that writes to the specified result.
|
||||
|
||||
#### Destructor
|
||||
|
||||
virtual ~basic_cbor_encoder()
|
||||
|
||||
### Inherited from [basic_json_content_handler](../json_content_handler.md)
|
||||
|
||||
#### Member functions
|
||||
|
||||
bool begin_object(semantic_tag tag=semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool begin_object(size_t length,
|
||||
semantic_tag tag=semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool end_object(const ser_context& context = null_ser_context())
|
||||
|
||||
bool begin_array(semantic_tag tag=semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool begin_array(semantic_tag tag=semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool end_array(const ser_context& context=null_ser_context());
|
||||
|
||||
bool name(const string_view_type& name,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool string_value(const string_view_type& value,
|
||||
semantic_tag tag = semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool byte_string_value(const byte_string_view& b,
|
||||
semantic_tag tag=semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool byte_string_value(const uint8_t* p, size_t size,
|
||||
semantic_tag tag=semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool int64_value(int64_t value,
|
||||
semantic_tag tag = semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool uint64_value(uint64_t value,
|
||||
semantic_tag tag = semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool double_value(double value,
|
||||
semantic_tag tag = semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool bool_value(bool value,
|
||||
semantic_tag tag = semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool null_value(semantic_tag tag = semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
void flush()
|
||||
|
||||
### Examples
|
||||
|
||||
#### Encode to CBOR buffer
|
||||
|
||||
```c++
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons_ext/cbor/cbor.hpp>
|
||||
#include <iomanip>
|
||||
|
||||
int main()
|
||||
{
|
||||
std::vector<uint8_t> buffer;
|
||||
cbor::cbor_bytes_encoder encoder(buffer);
|
||||
|
||||
encoder.begin_array(); // Indefinite length array
|
||||
encoder.string_value("cat");
|
||||
encoder.byte_string_value(byte_string({'p','u','r','r'}));
|
||||
encoder.byte_string_value(byte_string({'h','i','s','s'}),
|
||||
semantic_tag::base64); // suggested conversion to base64
|
||||
encoder.int64_value(1431027667, semantic_tag::timestamp);
|
||||
encoder.end_array();
|
||||
encoder.flush();
|
||||
|
||||
for (auto c : buffer)
|
||||
{
|
||||
std::cout << std::hex << std::setprecision(2) << std::setw(2)
|
||||
<< std::noshowbase << std::setfill('0') << static_cast<int>(c);
|
||||
}
|
||||
std::cout << "\n\n";
|
||||
|
||||
/*
|
||||
9f -- Start indefinte length array
|
||||
63 -- String value of length 3
|
||||
636174 -- "cat"
|
||||
44 -- Byte string value of length 4
|
||||
70757272 -- 'p''u''r''r'
|
||||
d6 - Expected conversion to base64
|
||||
44
|
||||
68697373 -- 'h''i''s''s'
|
||||
c1 -- Tag value 1 (seconds relative to 1970-01-01T00:00Z in UTC time)
|
||||
1a -- 32 bit unsigned integer
|
||||
554bbfd3 -- 1431027667
|
||||
ff -- "break"
|
||||
*/
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```
|
||||
9f636361744470757272d64468697373c11a554bbfd3ff
|
||||
```
|
||||
|
||||
#### Encode to CBOR stream
|
||||
|
||||
```c++
|
||||
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons_ext/cbor/cbor.hpp>
|
||||
#include <iomanip>
|
||||
|
||||
int main()
|
||||
{
|
||||
std::ostringstream os;
|
||||
cbor::cbor_encoder encoder(os);
|
||||
|
||||
encoder.begin_array(3); // array of length 3
|
||||
encoder.string_value("-18446744073709551617", semantic_tag::bigint);
|
||||
encoder.string_value("184467440737095516.16", semantic_tag::bigdec);
|
||||
encoder.int64_value(1431027667, semantic_tag::timestamp);
|
||||
encoder.end_array();
|
||||
encoder.flush();
|
||||
|
||||
for (auto c : os.str())
|
||||
{
|
||||
std::cout << std::hex << std::setprecision(2) << std::setw(2)
|
||||
<< std::noshowbase << std::setfill('0') << (int)unsigned char(c);
|
||||
}
|
||||
std::cout << "\n\n";
|
||||
|
||||
/*
|
||||
83 -- array of length 3
|
||||
c3 -- Tag 3 (negative bignum)
|
||||
49 -- Byte string value of length 9
|
||||
010000000000000000 -- Bytes content
|
||||
c4 -- Tag 4 (decimal fraction)
|
||||
82 -- Array of length 2
|
||||
21 -- -2 (exponent)
|
||||
c2 Tag 2 (positive bignum)
|
||||
49 -- Byte string value of length 9
|
||||
010000000000000000
|
||||
c1 -- Tag 1 (seconds relative to 1970-01-01T00:00Z in UTC time)
|
||||
1a -- 32 bit unsigned integer
|
||||
554bbfd3 -- 1431027667
|
||||
*/
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```
|
||||
83c349010000000000000000c48221c249010000000000000000c11a554bbfd3
|
||||
```
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
### jsoncons::cbor::cbor_options
|
||||
|
||||
Specifies options for encoding and decoding CBOR.
|
||||
|
||||
#### Header
|
||||
```c++
|
||||
#include <jsoncons/cbor/cbor_options.hpp>
|
||||
```
|
||||
|
||||
![cbor_options](./diagrams/cbor_options.png)
|
||||
|
||||
#### Constructors
|
||||
|
||||
cbor_options()
|
||||
Constructs a `cbor_options` with default values.
|
||||
|
||||
#### Modifiers
|
||||
|
||||
cbor_options& pack_strings(bool value)
|
||||
|
||||
If set to `true`, then encode will store text strings and
|
||||
byte strings once, and use string references to represent repeated occurences
|
||||
of the strings. Decoding the resulting CBOR requires a decoder
|
||||
that supports the
|
||||
[stringref extension to CBOR](http://cbor.schmorp.de/stringref), such as
|
||||
jsoncons itself, or [Perl CBOR::XS](http://software.schmorp.de/pkg/CBOR-XS.html)
|
||||
|
||||
If set to `false` (the default), then encode
|
||||
will encode strings the usual CBOR way.
|
||||
|
||||
This option does not affect decode - jsoncons will always decode
|
||||
string references if present.
|
||||
|
||||
#### Static member functions
|
||||
|
||||
static const cbor_options& default_options()
|
||||
Default CBOR encode and decode options.
|
||||
|
||||
### See also
|
||||
|
||||
[cbor_decode_options](cbor_decode_options.md)
|
||||
[cbor_encode_options](cbor_encode_options.md)
|
||||
|
|
@ -1,240 +0,0 @@
|
|||
### jsoncons::cbor::decode_cbor
|
||||
|
||||
Decodes a [Concise Binary Object Representation](http://cbor.io/) data format into a C++ data structure.
|
||||
|
||||
#### Header
|
||||
```c++
|
||||
#include <jsoncons_ext/cbor/cbor.hpp>
|
||||
|
||||
template<class T>
|
||||
T decode_cbor(const std::vector<uint8_t>& v); // (1)
|
||||
|
||||
template<class T>
|
||||
T decode_cbor(std::istream& is); // (2)
|
||||
```
|
||||
|
||||
(1) Reads a CBOR bytes buffer into a type T if T is an instantiation of [basic_json](../json.md)
|
||||
or if T supports [json_type_traits](../json_type_traits.md).
|
||||
|
||||
(2) Reads a CBOR binary stream into a type T if T is an instantiation of [basic_json](../json.md)
|
||||
or if T supports [json_type_traits](../json_type_traits.md).
|
||||
|
||||
#### Exceptions
|
||||
|
||||
Throws [ser_error](../ser_error.md) if parsing fails.
|
||||
|
||||
### Examples
|
||||
|
||||
#### Round trip (JSON to CBOR bytes back to JSON)
|
||||
|
||||
```c++
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons_ext/cbor/cbor.hpp>
|
||||
|
||||
using namespace jsoncons;
|
||||
|
||||
int main()
|
||||
{
|
||||
ojson j1 = ojson::parse(R"(
|
||||
{
|
||||
"application": "hiking",
|
||||
"reputons": [
|
||||
{
|
||||
"rater": "HikingAsylum.example.com",
|
||||
"assertion": "strong-hiker",
|
||||
"rated": "Marilyn C",
|
||||
"rating": 0.90
|
||||
}
|
||||
]
|
||||
}
|
||||
)");
|
||||
|
||||
std::vector<uint8_t> v;
|
||||
cbor::encode_cbor(j1, v);
|
||||
|
||||
ojson j2 = cbor::decode_cbor<ojson>(v);
|
||||
std::cout << pretty_print(j2) << std::endl;
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```json
|
||||
{
|
||||
"application": "hiking",
|
||||
"reputons": [
|
||||
{
|
||||
"rater": "HikingAsylum.example.com",
|
||||
"assertion": "strong-hiker",
|
||||
"rated": "Marilyn C",
|
||||
"rating": 0.9
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### Round trip (JSON to CBOR file back to JSON)
|
||||
|
||||
```c++
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons_ext/cbor/cbor.hpp>
|
||||
|
||||
using namespace jsoncons;
|
||||
|
||||
int main()
|
||||
{
|
||||
json j = json::parse(R"(
|
||||
{
|
||||
"application": "hiking",
|
||||
"reputons": [
|
||||
{
|
||||
"rater": "HikingAsylum.example.com",
|
||||
"assertion": "strong-hiker",
|
||||
"rated": "Marilyn C",
|
||||
"rating": 0.90
|
||||
}
|
||||
]
|
||||
}
|
||||
)");
|
||||
|
||||
std::ofstream os;
|
||||
os.open("./output/store.cbor", std::ios::binary | std::ios::out);
|
||||
cbor::encode_cbor(j,os);
|
||||
|
||||
std::vector<uint8_t> v;
|
||||
std::ifstream is;
|
||||
is.open("./output/store.cbor", std::ios::binary | std::ios::in);
|
||||
|
||||
json j2 = cbor::decode_cbor<json>(is);
|
||||
|
||||
std::cout << pretty_print(j2) << std::endl;
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```json
|
||||
{
|
||||
"application": "hiking",
|
||||
"reputons": [
|
||||
{
|
||||
"assertion": "strong-hiker",
|
||||
"rated": "Marilyn C",
|
||||
"rater": "HikingAsylum.example.com",
|
||||
"rating": 0.9
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### Decode CBOR byte string
|
||||
|
||||
```c++
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons_ext/cbor/cbor.hpp>
|
||||
|
||||
using namespace jsoncons;
|
||||
|
||||
int main()
|
||||
{
|
||||
// byte string of length 5
|
||||
std::vector<uint8_t> buf = {0x45,'H','e','l','l','o'};
|
||||
json j = cbor::decode_cbor<json>(buf);
|
||||
|
||||
auto bs = j.as<byte_string>();
|
||||
|
||||
// byte_string to ostream displays as hex
|
||||
std::cout << "(1) "<< bs << "\n\n";
|
||||
|
||||
// byte string value to JSON text becomes base64url
|
||||
std::cout << "(2) " << j << std::endl;
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```
|
||||
(1) 0x480x650x6c0x6c0x6f
|
||||
|
||||
(2) "SGVsbG8"
|
||||
```
|
||||
|
||||
#### Decode CBOR byte string with base64 encoding hint
|
||||
|
||||
```c++
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons_ext/cbor/cbor.hpp>
|
||||
|
||||
using namespace jsoncons;
|
||||
|
||||
int main()
|
||||
{
|
||||
// semantic tag indicating expected conversion to base64
|
||||
// followed by byte string of length 5
|
||||
std::vector<uint8_t> buf = {0xd6,0x45,'H','e','l','l','o'};
|
||||
json j = cbor::decode_cbor<json>(buf);
|
||||
|
||||
auto bs = j.as<byte_string>();
|
||||
|
||||
// byte_string to ostream displays as hex
|
||||
std::cout << "(1) "<< bs << "\n\n";
|
||||
|
||||
// byte string value to JSON text becomes base64
|
||||
std::cout << "(2) " << j << std::endl;
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```
|
||||
(1) 0x480x650x6c0x6c0x6f
|
||||
|
||||
(2) "SGVsbG8="
|
||||
```
|
||||
|
||||
#### Decode packed strings [stringref-namespace, stringref](http://cbor.schmorp.de/stringref)
|
||||
|
||||
This example taken from [CBOR stringref extension](http://cbor.schmorp.de/stringref) shows three stringref-namespace tags,
|
||||
with two nested inside another:
|
||||
|
||||
```c++
|
||||
int main()
|
||||
{
|
||||
std::vector<uint8_t> v = {0xd9,0x01,0x00, // tag(256)
|
||||
0x85, // array(5)
|
||||
0x63, // text(3)
|
||||
0x61,0x61,0x61, // "aaa"
|
||||
0xd8, 0x19, // tag(25)
|
||||
0x00, // unsigned(0)
|
||||
0xd9, 0x01,0x00, // tag(256)
|
||||
0x83, // array(3)
|
||||
0x63, // text(3)
|
||||
0x62,0x62,0x62, // "bbb"
|
||||
0x63, // text(3)
|
||||
0x61,0x61,0x61, // "aaa"
|
||||
0xd8, 0x19, // tag(25)
|
||||
0x01, // unsigned(1)
|
||||
0xd9, 0x01,0x00, // tag(256)
|
||||
0x82, // array(2)
|
||||
0x63, // text(3)
|
||||
0x63,0x63,0x63, // "ccc"
|
||||
0xd8, 0x19, // tag(25)
|
||||
0x00, // unsigned(0)
|
||||
0xd8, 0x19, // tag(25)
|
||||
0x00 // unsigned(0)
|
||||
};
|
||||
|
||||
ojson j = cbor::decode_cbor<ojson>(v);
|
||||
|
||||
std::cout << pretty_print(j) << "\n";
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```
|
||||
[
|
||||
"aaa",
|
||||
"aaa",
|
||||
["bbb", "aaa", "aaa"],
|
||||
["ccc", "ccc"],
|
||||
"aaa"
|
||||
]
|
||||
```
|
||||
|
||||
#### See also
|
||||
|
||||
- [byte_string](../byte_string.md)
|
||||
- [encode_cbor](encode_cbor.md) encodes a json value to the [Concise Binary Object Representation](http://cbor.io/) data format.
|
||||
|
||||
|
|
@ -1 +0,0 @@
|
|||
<mxfile modified="2019-02-06T01:28:05.917Z" host="www.draw.io" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.81 Safari/537.36" etag="HJRvV8Pagh8sW1Um5jfB" version="10.1.8" type="device"><diagram id="iK-0d-7Yl-5MlnfMu26I" name="Page-1">3Vffb9owEP5reGRKYmD0sYWu21CrdUyCPiE3vibeHJs5BsL++p2JQ35WbacKTfCC77Pv7Pvu43rtkUmS3Wi6jm8VA9ELPJb1yLQXBL4X+PhlkX2OkEGQA5HmzB0qgTn/A4WnQzecQVo7aJQShq/rYKikhNDUMKq12tWPPSlRv3VNI2gB85CKNrrgzMQ5Oh56Jf4ZeBQXN/ue20locdgBaUyZ2lUgct0jE62UyVdJNgFhySt4yf0+PbN7fJgGaV7jcH33I5Oz+3kcTH7PzOI2eci+9l2ULRUbl/AjTXm4+pkquUJODQZfxVQyAboXjATedPVoV5FddSGHVM2+4E+rjWRgn+Dh9i7mBuZrGtrdHSoGsdgkAi3/6F1NqXgfaANZBXIp3oBKwOg9HnG7Y8e2k5tfsL8ri+ePHBZXCjdwGHV6iY6RS0px4Vh9A8Mfn2E4fFR6lYLmVKDoT0DuExdiooTSB18Chw/iqdHqF1R2yIhcEPY+5XhVPQanrMe4VY8WrSDZpW0daIWCplitOpOQcbN0pNv1g11/GDprmlW2pvvCkPj4ZRHAGhUva5ZuB6vwe7YGqdroEF4WnqE6AvNyCwBWa4TtilYqNuwoWIFpENTwbb19dlXR3fBNcczsKJhBXS8BaeggT9s5VbtdI85FQ3fjRpycllacg6SOSb9KZdH2Ng5md0v6HaL+4n4G2xn0h2eoss5EyVmqZ9AINDqtekZnop5q7+lM9P/qPUOv0TS8f5WP39Chf1r9tGeOLzLGUcNQiT9mHMY5jTRNWqLCP+qmLqP6cCCVhMYk4SAcYiJptYgSwGGGXNkRgeMYfek2Es6YvaZzSqnPMe8wdviN9h94HWMH6VBS8PaxA81yiM8rWP4rRK7/Ag==</diagram></mxfile>
|
Before Width: | Height: | Size: 5.6 KiB |
|
@ -1 +0,0 @@
|
|||
<mxfile modified="2019-03-28T19:07:58.025Z" host="www.draw.io" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36" etag="HL3CZdJq60KpSP7znTE-" version="10.5.9" type="device"><diagram id="aNkMF165W3cufMvMLNcI" name="Page-1">zZbLbtswEEW/RssUetSPbWOnySItghpo05XAimOJjUQqFBVJ/fqS0VBPJ04Lo/XG4FxyhuSZa0JOsMnqa0ny5JOgkDq+S2sn2Dq+v/I9/WuEphWCJQqxZLSVBsKO/QIUXVRLRqEYLVRCpIrlYzESnEOkRhqRUlTjZXuRjnfNSQwzYReRdK5+Y1QlrbpeuL1+AyxO7M6eizMZsYtRKBJCRTWQgisn2EghVDvK6g2khp3l0uZ9fGG2O5gErt6SsP/a7L/kDzeP4nP4uA63l+Vtc4FVnkha4oV/kIJF4c9C8JBCpNsZilwxwQu8hWosGilKTsFUd53gskqYgl1OIjNbaS9oLVFZqiNPD+entVuDVFAPJDz9NYgMlGz0Epx9jyDRSWsMq74t3hK1ZNASm0bQCXFXuIelB8jrD9j5r7EDfs7sOlD/DV7wGrxzoeYvJ9j8A9j8f4ltOcM2gwScfjAPn46ilBQa6pgL1EzdI0Iz/m7G7xYYbevB1LaxAdeHv7cFTDDIMmGf9hzZvBd7UIhSRnDcH4rIGNTxPyHQ0TM+7+igY4sDDbOahJQo9jR+/A91EXe4E0zfrDNMZ4ZmYiBbor03Zg0f62mh1aSQNynUgpkVejZVd+2/99nqBD47tWeOesE7Ky/MHo/po/BWL6wnVvBPZQUd9p8f7fL+Gy64+g0=</diagram></mxfile>
|
|
@ -1,273 +0,0 @@
|
|||
### jsoncons::cbor::encode_cbor
|
||||
|
||||
Encodes a C++ data structure to the [Concise Binary Object Representation](http://cbor.io/) data format.
|
||||
|
||||
#### Header
|
||||
```c++
|
||||
#include <jsoncons_ext/cbor/cbor.hpp>
|
||||
|
||||
template<class T>
|
||||
void encode_cbor(const T& val, std::vector<uint8_t>& buffer,
|
||||
const cbor_encode_options& options = cbor_options::default_options()); // (1)
|
||||
|
||||
template<class T>
|
||||
void encode_cbor(const T& val, std::ostream& os,
|
||||
const cbor_encode_options& options = cbor_options::default_options()); // (2)
|
||||
```
|
||||
|
||||
(1) Writes a value of type T into a bytes buffer in the CBOR data format. Type T must be an instantiation of [basic_json](../json.md)
|
||||
or support [json_type_traits](../json_type_traits.md). Uses the [encode options](cbor_options.md)
|
||||
supplied or defaults.
|
||||
|
||||
(2) Writes a value of type T into a binary stream in the CBOR data format. Type T must be an instantiation of [basic_json](../json.md)
|
||||
or support [json_type_traits](../json_type_traits.md). Uses the [encode options](cbor_options.md)
|
||||
supplied or defaults.
|
||||
|
||||
#### See also
|
||||
|
||||
- [decode_cbor](decode_cbor) decodes a [Concise Binary Object Representation](http://cbor.io/) data format to a json value.
|
||||
|
||||
### Examples
|
||||
|
||||
#### cbor example
|
||||
|
||||
```c++
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons_ext/cbor/cbor.hpp>
|
||||
|
||||
using namespace jsoncons;
|
||||
|
||||
int main()
|
||||
{
|
||||
ojson j1;
|
||||
j1["zero"] = 0;
|
||||
j1["one"] = 1;
|
||||
j1["two"] = 2;
|
||||
j1["null"] = null_type();
|
||||
j1["true"] = true;
|
||||
j1["false"] = false;
|
||||
j1["max int64_t"] = (std::numeric_limits<int64_t>::max)();
|
||||
j1["max uint64_t"] = (std::numeric_limits<uint64_t>::max)();
|
||||
j1["min int64_t"] = (std::numeric_limits<int64_t>::lowest)();
|
||||
j1["max int32_t"] = (std::numeric_limits<int32_t>::max)();
|
||||
j1["max uint32_t"] = (std::numeric_limits<uint32_t>::max)();
|
||||
j1["min int32_t"] = (std::numeric_limits<int32_t>::lowest)();
|
||||
j1["max int16_t"] = (std::numeric_limits<int16_t>::max)();
|
||||
j1["max uint16_t"] = (std::numeric_limits<uint16_t>::max)();
|
||||
j1["min int16_t"] = (std::numeric_limits<int16_t>::lowest)();
|
||||
j1["max int8_t"] = (std::numeric_limits<int8_t>::max)();
|
||||
j1["max uint8_t"] = (std::numeric_limits<uint8_t>::max)();
|
||||
j1["min int8_t"] = (std::numeric_limits<int8_t>::lowest)();
|
||||
j1["max double"] = (std::numeric_limits<double>::max)();
|
||||
j1["min double"] = (std::numeric_limits<double>::lowest)();
|
||||
j1["max float"] = (std::numeric_limits<float>::max)();
|
||||
j1["zero float"] = 0.0;
|
||||
j1["min float"] = (std::numeric_limits<float>::lowest)();
|
||||
j1["Key too long for small string optimization"] = "String too long for small string optimization";
|
||||
|
||||
std::vector<uint8_t> v;
|
||||
cbor::encode_cbor(j1, v);
|
||||
|
||||
ojson j2 = cbor::decode_cbor<ojson>(v);
|
||||
|
||||
std::cout << pretty_print(j2) << std::endl;
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```json
|
||||
{
|
||||
"zero": 0,
|
||||
"one": 1,
|
||||
"two": 2,
|
||||
"null": null,
|
||||
"true": true,
|
||||
"false": false,
|
||||
"max int64_t": 9223372036854775807,
|
||||
"max uint64_t": 18446744073709551615,
|
||||
"min int64_t": -9223372036854775808,
|
||||
"max int32_t": 2147483647,
|
||||
"max uint32_t": 4294967295,
|
||||
"min int32_t": -2147483648,
|
||||
"max int16_t": 32767,
|
||||
"max uint16_t": 65535,
|
||||
"min int16_t": -32768,
|
||||
"max int8_t": 127,
|
||||
"max uint8_t": 255,
|
||||
"min int8_t": -128,
|
||||
"max double": 1.79769313486232e+308,
|
||||
"min double": -1.79769313486232e+308,
|
||||
"max float": 3.40282346638529e+038,
|
||||
"zero float": 0.0,
|
||||
"min float": -3.40282346638529e+038,
|
||||
"Key too long for small string optimization": "String too long for small string optimization"
|
||||
}
|
||||
```
|
||||
|
||||
#### Encode CBOR byte string
|
||||
|
||||
```c++
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons_ext/cbor/cbor.hpp>
|
||||
|
||||
using namespace jsoncons;
|
||||
|
||||
int main()
|
||||
{
|
||||
// construct byte string value
|
||||
json j(byte_string("Hello"));
|
||||
|
||||
std::vector<uint8_t> buf;
|
||||
cbor::encode_cbor(j, buf);
|
||||
|
||||
std::cout << std::hex << std::showbase << "(1) ";
|
||||
for (auto c : buf)
|
||||
{
|
||||
std::cout << (int)c;
|
||||
}
|
||||
std::cout << std::dec << "\n\n";
|
||||
|
||||
json j2 = cbor::decode_cbor<json>(buf);
|
||||
std::cout << "(2) " << j2 << std::endl;
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```
|
||||
(1) 0x450x480x650x6c0x6c0x6f
|
||||
|
||||
(2) "SGVsbG8"
|
||||
```
|
||||
|
||||
#### Encode byte string with encoding hint
|
||||
|
||||
```c++
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons_ext/cbor/cbor.hpp>
|
||||
|
||||
using namespace jsoncons;
|
||||
|
||||
int main()
|
||||
{
|
||||
// construct byte string value
|
||||
json j1(byte_string("Hello"), semantic_tag::base64);
|
||||
|
||||
std::vector<uint8_t> buf;
|
||||
cbor::encode_cbor(j1, buf);
|
||||
|
||||
std::cout << std::hex << std::showbase << "(1) ";
|
||||
for (auto c : buf)
|
||||
{
|
||||
std::cout << (int)c;
|
||||
}
|
||||
std::cout << std::dec << "\n\n";
|
||||
|
||||
json j2 = cbor::decode_cbor<json>(buf);
|
||||
std::cout << "(2) " << j2 << std::endl;
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```
|
||||
(1) 0xd60x450x480x650x6c0x6c0x6f
|
||||
|
||||
(2) "SGVsbG8="
|
||||
```
|
||||
|
||||
#### Encode packed strings [stringref-namespace, stringref](http://cbor.schmorp.de/stringref)
|
||||
|
||||
This example taken from [CBOR stringref extension](http://cbor.schmorp.de/stringref) shows how to encode a
|
||||
data structure that contains many repeated strings more efficiently.
|
||||
|
||||
```c++
|
||||
#include <iomanip>
|
||||
#include <cassert>
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons_ext/cbor/cbor.hpp>
|
||||
|
||||
using namespace jsoncons;
|
||||
|
||||
int main()
|
||||
{
|
||||
ojson j = ojson::parse(R"(
|
||||
[
|
||||
{
|
||||
"name" : "Cocktail",
|
||||
"count" : 417,
|
||||
"rank" : 4
|
||||
},
|
||||
{
|
||||
"rank" : 4,
|
||||
"count" : 312,
|
||||
"name" : "Bath"
|
||||
},
|
||||
{
|
||||
"count" : 691,
|
||||
"name" : "Food",
|
||||
"rank" : 4
|
||||
}
|
||||
]
|
||||
)");
|
||||
|
||||
cbor::cbor_options options;
|
||||
options.pack_strings(true);
|
||||
std::vector<uint8_t> buf;
|
||||
|
||||
cbor::encode_cbor(j, buf, options);
|
||||
|
||||
for (auto c : buf)
|
||||
{
|
||||
std::cout << std::hex << std::setprecision(2) << std::setw(2)
|
||||
<< std::noshowbase << std::setfill('0') << static_cast<int>(c);
|
||||
}
|
||||
std::cout << "\n";
|
||||
|
||||
/*
|
||||
d90100 -- tag (256)
|
||||
83 -- array(3)
|
||||
a3 -- map(3)
|
||||
64 -- text string (4)
|
||||
6e616d65 -- "name"
|
||||
68 -- text string (8)
|
||||
436f636b7461696c -- "Cocktail"
|
||||
65 -- text string (5)
|
||||
636f756e74 -- "count"
|
||||
1901a1 -- unsigned(417)
|
||||
64 -- text string (4)
|
||||
72616e6b -- "rank"
|
||||
04 -- unsigned(4)
|
||||
a3 -- map(3)
|
||||
d819 -- tag(25)
|
||||
03 -- unsigned(3)
|
||||
04 -- unsigned(4)
|
||||
d819 -- tag(25)
|
||||
02 -- unsigned(2)
|
||||
190138 -- unsigned(312)
|
||||
d819 -- tag(25)
|
||||
00 -- unsigned(0)
|
||||
64 -- text string(4)
|
||||
42617468 -- "Bath"
|
||||
a3 -- map(3)
|
||||
d819 -- tag(25)
|
||||
02 -- unsigned(2)
|
||||
1902b3 -- unsigned(691)
|
||||
d819 -- tag(25)
|
||||
00 -- unsigned(0)
|
||||
64 - text string(4)
|
||||
466f6f64 -- "Food"
|
||||
d819 -- tag(25)
|
||||
03 -- unsigned(3)
|
||||
04 -- unsigned(4)
|
||||
*/
|
||||
|
||||
ojson j2 = cbor::decode_cbor<ojson>(buf);
|
||||
assert(j2 == j);
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```
|
||||
d9010083a3646e616d6568436f636b7461696c65636f756e741901a16472616e6b04a3d8190304d81902190138d819006442617468a3d819021902b3d8190064466f6f64d8190304
|
||||
```
|
||||
|
||||
#### See also
|
||||
|
||||
- [byte_string](../byte_string.md)
|
||||
- [decode_cbor](decode_cbor.md) decodes a [Concise Binary Object Representation](http://cbor.io/) data format to a json value.
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
### jsoncons::chars_format
|
||||
|
||||
```c++
|
||||
#if !defined(JSONCONS_NO_TO_CHARS)
|
||||
using chars_format = std::chars_format;
|
||||
#else
|
||||
enum class chars_format : uint8_t {fixed=1,scientific=2,hex=4,general=fixed|scientific};
|
||||
#endif
|
||||
```
|
||||
|
||||
#### Header
|
||||
```c++
|
||||
#include <jsoncons/jsoncons_utilities.hpp>
|
||||
```
|
||||
|
||||
A bitmask type used to specify floating-point formatting, typedefed to [std::chars_format](http://en.cppreference.com/w/cpp/utility/chars_format) if `JSONCONS_NO_TO_CHARS` is undefined.
|
||||
|
|
@ -1,175 +0,0 @@
|
|||
### csv extension
|
||||
|
||||
The csv extension implements decode from and encode to the [CSV format](https://www.rfc-editor.org/rfc/rfc4180.txt)
|
||||
You can either parse into or serialize from a variant-like structure, [basic_json](../json.md), or your own
|
||||
data structures, using [json_type_traits](../json_type_traits.md).
|
||||
|
||||
[decode_csv](decode_csv.md)
|
||||
|
||||
[encode_csv](encode_csv.md)
|
||||
|
||||
[csv_options](csv_options.md)
|
||||
|
||||
[csv_reader](csv_reader.md)
|
||||
|
||||
[csv_encoder](csv_encoder.md)
|
||||
|
||||
### Examples
|
||||
|
||||
#### Decode a CSV source to a basic_json value
|
||||
|
||||
Example file (sales.csv)
|
||||
```csv
|
||||
customer_name,has_coupon,phone_number,zip_code,sales_tax_rate,total_amount
|
||||
"John Roe",true,0272561313,01001,0.05,431.65
|
||||
"Jane Doe",false,416-272-2561,55416,0.15,480.70
|
||||
"Joe Bloggs",false,"4162722561","55416",0.15,300.70
|
||||
"John Smith",FALSE,NULL,22313-1450,0.15,300.70
|
||||
```
|
||||
|
||||
```c++
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons_ext/csv/csv_reader.hpp>
|
||||
#include <fstream>
|
||||
|
||||
using namespace jsoncons;
|
||||
|
||||
int main()
|
||||
{
|
||||
csv::csv_options options;
|
||||
options.assume_header(true)
|
||||
.mapping(csv::mapping_type::n_objects);
|
||||
|
||||
std::ifstream is1("input/sales.csv");
|
||||
ojson j1 = csv::decode_csv<ojson>(is1,options);
|
||||
std::cout << "\n(1)\n"<< pretty_print(j1) << "\n";
|
||||
|
||||
options.mapping(csv::mapping_type::n_rows);
|
||||
std::ifstream is2("input/sales.csv");
|
||||
ojson j2 = csv::decode_csv<ojson>(is2,options);
|
||||
std::cout << "\n(2)\n"<< pretty_print(j2) << "\n";
|
||||
|
||||
options.mapping(csv::mapping_type::m_columns);
|
||||
std::ifstream is3("input/sales.csv");
|
||||
ojson j3 = csv::decode_csv<ojson>(is3,options);
|
||||
std::cout << "\n(3)\n"<< pretty_print(j3) << "\n";
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```json
|
||||
(1)
|
||||
[
|
||||
{
|
||||
"customer_name": "John Roe",
|
||||
"has_coupon": true,
|
||||
"phone_number": "0272561313",
|
||||
"zip_code": "01001",
|
||||
"sales_tax_rate": 0.05,
|
||||
"total_amount": 431.65
|
||||
},
|
||||
{
|
||||
"customer_name": "Jane Doe",
|
||||
"has_coupon": false,
|
||||
"phone_number": "416-272-2561",
|
||||
"zip_code": 55416,
|
||||
"sales_tax_rate": 0.15,
|
||||
"total_amount": 480.7
|
||||
},
|
||||
{
|
||||
"customer_name": "Joe Bloggs",
|
||||
"has_coupon": false,
|
||||
"phone_number": "4162722561",
|
||||
"zip_code": "55416",
|
||||
"sales_tax_rate": 0.15,
|
||||
"total_amount": 300.7
|
||||
},
|
||||
{
|
||||
"customer_name": "John Smith",
|
||||
"has_coupon": false,
|
||||
"phone_number": null,
|
||||
"zip_code": "22313-1450",
|
||||
"sales_tax_rate": 0.15,
|
||||
"total_amount": 300.7
|
||||
}
|
||||
]
|
||||
|
||||
(2)
|
||||
[
|
||||
["customer_name","has_coupon","phone_number","zip_code","sales_tax_rate","total_amount"],
|
||||
["John Roe",true,"0272561313","01001",0.05,431.65],
|
||||
["Jane Doe",false,"416-272-2561",55416,0.15,480.7],
|
||||
["Joe Bloggs",false,"4162722561","55416",0.15,300.7],
|
||||
["John Smith",false,null,"22313-1450",0.15,300.7]
|
||||
]
|
||||
|
||||
(3)
|
||||
{
|
||||
"customer_name": ["John Roe","Jane Doe","Joe Bloggs","John Smith"],
|
||||
"has_coupon": [true,false,false,false],
|
||||
"phone_number": ["0272561313","416-272-2561",4162722561,null],
|
||||
"zip_code": ["01001",55416,55416,"22313-1450"],
|
||||
"sales_tax_rate": [0.05,0.15,0.15,0.15],
|
||||
"total_amount": [431.65,480.7,300.7,300.7]
|
||||
}
|
||||
```
|
||||
|
||||
#### Convert a CSV source to a C++ data structure that satisfies [json_type_traits](../json_type_traits.md) requirements, and back
|
||||
|
||||
```c++
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons_ext/csv/csv.hpp>
|
||||
#include <iostream>
|
||||
|
||||
using namespace jsoncons;
|
||||
|
||||
int main()
|
||||
{
|
||||
const std::string input = R"(Date,1Y,2Y,3Y,5Y
|
||||
2017-01-09,0.0062,0.0075,0.0083,0.011
|
||||
2017-01-08,0.0063,0.0076,0.0084,0.0112
|
||||
2017-01-08,0.0063,0.0076,0.0084,0.0112
|
||||
)";
|
||||
|
||||
csv::csv_options ioptions;
|
||||
ioptions.header_lines(1)
|
||||
.mapping(csv::mapping_type::n_rows);
|
||||
|
||||
typedef std::vector<std::tuple<std::string,double,double,double,double>> table_type;
|
||||
|
||||
table_type table = csv::decode_csv<table_type>(input,ioptions);
|
||||
|
||||
std::cout << "(1)\n";
|
||||
for (const auto& row : table)
|
||||
{
|
||||
std::cout << std::get<0>(row) << ","
|
||||
<< std::get<1>(row) << ","
|
||||
<< std::get<2>(row) << ","
|
||||
<< std::get<3>(row) << ","
|
||||
<< std::get<4>(row) << "\n";
|
||||
}
|
||||
std::cout << "\n";
|
||||
|
||||
std::string output;
|
||||
|
||||
csv::csv_options ooptions;
|
||||
ooptions.column_names("Date,1Y,2Y,3Y,5Y");
|
||||
csv::encode_csv<table_type>(table, output, ooptions);
|
||||
|
||||
std::cout << "(2)\n";
|
||||
std::cout << output << "\n";
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```
|
||||
(1)
|
||||
2017-01-09,0.0062,0.0075,0.0083,0.011
|
||||
2017-01-08,0.0063,0.0076,0.0084,0.011
|
||||
2017-01-08,0.0063,0.0076,0.0084,0.011
|
||||
|
||||
(2)
|
||||
Date,1Y,2Y,3Y,5Y
|
||||
2017-01-09,0.0062,0.0075,0.0083,0.011
|
||||
2017-01-08,0.0063,0.0076,0.0084,0.0112
|
||||
2017-01-08,0.0063,0.0076,0.0084,0.0112
|
||||
```
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
### jsoncons::csv::csv_decode_options
|
||||
|
||||
```c++
|
||||
typedef basic_csv_decode_options<char> csv_decode_options
|
||||
```
|
||||
|
||||
An abstract class that defines accessors for CSV decode options.
|
||||
|
||||
#### Header
|
||||
```c++
|
||||
#include <jsoncons/csv/csv_options.hpp>
|
||||
```
|
||||
|
||||
#### Implementing classes
|
||||
|
||||
[csv_options](csv_options.md)
|
||||
|
||||
#### Accessors
|
||||
|
||||
virtual size_t header_lines() const = 0;
|
||||
|
||||
virtual bool assume_header() const = 0;
|
||||
|
||||
virtual bool ignore_empty_values() const = 0;
|
||||
|
||||
virtual bool ignore_empty_lines() const = 0;
|
||||
|
||||
virtual bool trim_leading() const = 0;
|
||||
|
||||
virtual bool trim_trailing() const = 0;
|
||||
|
||||
virtual bool trim_leading_inside_quotes() const = 0;
|
||||
|
||||
virtual bool trim_trailing_inside_quotes() const = 0;
|
||||
|
||||
virtual bool trim() const = 0;
|
||||
|
||||
virtual bool trim_inside_quotes() const = 0;
|
||||
|
||||
virtual bool unquoted_empty_value_is_null() const = 0;
|
||||
|
||||
virtual std::vector<string_type> column_names() const = 0;
|
||||
|
||||
virtual std::vector<csv_type_info> column_types() const = 0;
|
||||
|
||||
virtual std::vector<string_type> column_defaults() const = 0;
|
||||
|
||||
virtual CharT field_delimiter() const = 0;
|
||||
|
||||
virtual std::pair<CharT,bool> subfield_delimiter() const = 0;
|
||||
|
||||
virtual string_type line_delimiter() const = 0;
|
||||
|
||||
virtual CharT quote_char() const = 0;
|
||||
|
||||
virtual bool infer_types() const = 0;
|
||||
|
||||
virtual bool lossless_number() const = 0;
|
||||
|
||||
virtual CharT quote_escape_char() const = 0;
|
||||
|
||||
virtual CharT comment_starter() const = 0;
|
||||
|
||||
virtual mapping_type mapping() const = 0;
|
||||
|
||||
virtual unsigned long max_lines() const = 0;
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
### jsoncons::csv::csv_encode_options
|
||||
|
||||
An abstract class that defines accessors for CSV encode options.
|
||||
|
||||
#### Header
|
||||
```c++
|
||||
#include <jsoncons/csv/csv_options.hpp>
|
||||
```
|
||||
|
||||
#### Implementing classes
|
||||
|
||||
[csv_options](csv_options.md)
|
||||
|
||||
#### Accessors
|
||||
|
||||
virtual chars_format floating_point_format() const = 0;
|
||||
|
||||
virtual int precision() const = 0;
|
||||
|
||||
virtual std::vector<string_type> column_names() const = 0;
|
||||
|
||||
virtual CharT field_delimiter() const = 0;
|
||||
|
||||
virtual std::pair<CharT,bool> subfield_delimiter() const = 0;
|
||||
|
||||
virtual string_type line_delimiter() const = 0;
|
||||
|
||||
virtual CharT quote_char() const = 0;
|
||||
|
||||
virtual CharT quote_escape_char() const = 0;
|
||||
|
||||
virtual quote_style_type quote_style() const = 0;
|
||||
|
|
@ -1,260 +0,0 @@
|
|||
### jsoncons::csv::basic_csv_encoder
|
||||
|
||||
```c++
|
||||
template<
|
||||
class CharT,
|
||||
class Result
|
||||
class Allocator=std::allocator<CharT>=std::allocator<CharT>>
|
||||
> class basic_csv_encoder : public jsoncons::basic_json_content_handler<CharT>
|
||||
```
|
||||
|
||||
`basic_csv_encoder` and `basic_json_compressed_encoder` are noncopyable and nonmoveable.
|
||||
|
||||
#### Header
|
||||
|
||||
#include <jsoncons_ext/csv/csv_encoder.hpp>
|
||||
|
||||
![csv_encoder](./diagrams/csv_encoder.png)
|
||||
|
||||
Four specializations for common character types and result types are defined:
|
||||
|
||||
Type |Definition
|
||||
---------------------------|------------------------------
|
||||
csv_encoder |basic_csv_encoder<char,jsoncons::stream_result<char>>
|
||||
json_string_encoder |basic_csv_encoder<char,jsoncons::string_result<std::string>>
|
||||
wcsv_encoder |basic_csv_encoder<wchar_t,jsoncons::stream_result<wchar_t>>
|
||||
wjson_string_encoder |basic_csv_encoder<wchar_t,jsoncons::string_result<std::wstring>>
|
||||
|
||||
#### Member types
|
||||
|
||||
Type |Definition
|
||||
---------------------------|------------------------------
|
||||
char_type |CharT
|
||||
result_type |Result
|
||||
string_view_type |
|
||||
|
||||
#### Constructors
|
||||
|
||||
explicit basic_csv_encoder(result_type result)
|
||||
Constructs a new csv encoder that is associated with the output adaptor `result`.
|
||||
|
||||
basic_csv_encoder(result_type result,
|
||||
const basic_csv_options<CharT>& options)
|
||||
Constructs a new csv encoder that is associated with the output adaptor `result`
|
||||
and uses the specified [csv options](csv_options.md).
|
||||
|
||||
#### Destructor
|
||||
|
||||
virtual ~basic_csv_encoder()
|
||||
|
||||
### Inherited from [basic_json_content_handler](../json_content_handler.md)
|
||||
|
||||
#### Member functions
|
||||
|
||||
bool begin_object(semantic_tag tag=semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool begin_object(size_t length,
|
||||
semantic_tag tag=semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool end_object(const ser_context& context = null_ser_context())
|
||||
|
||||
bool begin_array(semantic_tag tag=semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool begin_array(semantic_tag tag=semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool end_array(const ser_context& context=null_ser_context());
|
||||
|
||||
bool name(const string_view_type& name,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool string_value(const string_view_type& value,
|
||||
semantic_tag tag = semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool byte_string_value(const byte_string_view& b,
|
||||
semantic_tag tag=semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool byte_string_value(const uint8_t* p, size_t size,
|
||||
semantic_tag tag=semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool int64_value(int64_t value,
|
||||
semantic_tag tag = semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool uint64_value(uint64_t value,
|
||||
semantic_tag tag = semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool double_value(double value,
|
||||
semantic_tag tag = semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool bool_value(bool value,
|
||||
semantic_tag tag = semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
bool null_value(semantic_tag tag = semantic_tag::none,
|
||||
const ser_context& context=null_ser_context());
|
||||
|
||||
void flush()
|
||||
|
||||
### Examples
|
||||
|
||||
### Serializing an array of json values to a comma delimted file
|
||||
|
||||
#### JSON input file
|
||||
```json
|
||||
[
|
||||
["country_code","name"],
|
||||
["ABW","ARUBA"],
|
||||
["ATF","FRENCH SOUTHERN TERRITORIES, D.R. OF"],
|
||||
["VUT","VANUATU"],
|
||||
["WLF","WALLIS & FUTUNA ISLANDS"]
|
||||
]
|
||||
```
|
||||
Note
|
||||
|
||||
- The third array element has a value that contains a comma, in the CSV file this value will be quoted.
|
||||
|
||||
#### Serializing the comma delimited file with csv_encoder
|
||||
```c++
|
||||
std::string in_file = "input/countries.json";
|
||||
std::ifstream is(in_file);
|
||||
|
||||
json_decoder<json> decoder;
|
||||
json_reader reader(is,decoder);
|
||||
reader.read();
|
||||
json countries = decoder.get_result();
|
||||
|
||||
csv_encoder encoder(std::cout);
|
||||
|
||||
countries.dump(encoder);
|
||||
```
|
||||
#### Output
|
||||
```
|
||||
country_code,name
|
||||
ABW,ARUBA
|
||||
ATF,"FRENCH SOUTHERN TERRITORIES, D.R. OF"
|
||||
VUT,VANUATU
|
||||
WLF,WALLIS & FUTUNA ISLANDS
|
||||
```
|
||||
### Serializing an array of json objects to a tab delimted file
|
||||
|
||||
#### JSON input file
|
||||
```json
|
||||
[
|
||||
{
|
||||
"dept":"sales",
|
||||
"employee-name":"Smith, Matthew",
|
||||
"employee-no":"00000001",
|
||||
"note":"",
|
||||
"salary":"150,000.00"
|
||||
},
|
||||
{
|
||||
"dept":"sales",
|
||||
"employee-name":"Brown, Sarah",
|
||||
"employee-no":"00000002",
|
||||
"note":"",
|
||||
"salary":"89,000.00"
|
||||
},
|
||||
{
|
||||
"dept":"finance",
|
||||
"employee-name":"Oberc, Scott",
|
||||
"employee-no":"00000003",
|
||||
"salary":"110,000.00"
|
||||
},
|
||||
{
|
||||
"dept":"sales",
|
||||
"employee-name":"Scott, Colette",
|
||||
"employee-no":"00000004",
|
||||
"note":"\"Exemplary\" employee\nDependable, trustworthy",
|
||||
"comment":"Team player",
|
||||
"salary":"75,000.00"
|
||||
}
|
||||
]
|
||||
```
|
||||
Note
|
||||
|
||||
- The names in the first object in the array will be used for the header row of the CSV file
|
||||
- The fourth object has a `note` member whose value contains escaped quotes and an escaped new line character, in the CSV file, this value will be quoted, and it will contain a new line character and escaped quotes.
|
||||
|
||||
#### Dump json value to a tab delimited file
|
||||
```c++
|
||||
std::string in_file = "input/employees.json";
|
||||
std::ifstream is(in_file);
|
||||
|
||||
json_decoder<json> decoder;
|
||||
csv_options options;
|
||||
options.field_delimiter = '\t';
|
||||
|
||||
json_reader reader(is,decoder);
|
||||
reader.read();
|
||||
json employees = decoder.get_result();
|
||||
|
||||
csv_encoder encoder(std::cout,options);
|
||||
|
||||
employees.dump(encoder);
|
||||
```
|
||||
#### Tab delimited output file
|
||||
```
|
||||
dept employee-name employee-no note salary
|
||||
sales Smith, Matthew 00000001 150,000.00
|
||||
sales Brown, Sarah 00000002 89,000.00
|
||||
finance Oberc, Scott 00000003 110,000.00
|
||||
sales Scott, Colette 00000004 ""Exemplary"" employee
|
||||
Dependable, trustworthy 75,000.00
|
||||
```
|
||||
|
||||
#### Dump json value to csv file
|
||||
|
||||
```c++
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons_ext/csv/csv_encoder.hpp>
|
||||
|
||||
using namespace jsoncons;
|
||||
|
||||
int main()
|
||||
{
|
||||
const json books = json::parse(R"(
|
||||
[
|
||||
{
|
||||
"title" : "Kafka on the Shore",
|
||||
"author" : "Haruki Murakami",
|
||||
"price" : 25.17
|
||||
},
|
||||
{
|
||||
"title" : "Women: A Novel",
|
||||
"author" : "Charles Bukowski",
|
||||
"price" : 12.00
|
||||
},
|
||||
{
|
||||
"title" : "Cutter's Way",
|
||||
"author" : "Ivan Passer"
|
||||
}
|
||||
]
|
||||
)");
|
||||
|
||||
csv_options options;
|
||||
options.column_names("author,title,price");
|
||||
|
||||
csv_encoder encoder(std::cout, options);
|
||||
|
||||
books.dump(encoder);
|
||||
}
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```csv
|
||||
author,title,price
|
||||
Haruki Murakami,Kafka on the Shore,25.17
|
||||
Charles Bukowski,Women: A Novel,12.0
|
||||
Ivan Passer,Cutter's Way,
|
||||
```
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
### jsoncons::csv::csv_options
|
||||
|
||||
```c++
|
||||
typedef basic_csv_options<char> csv_options
|
||||
```
|
||||
Specifies options for encoding and decoding csv data. The `csv_options` class is an instantiation of the `basic_csv_options` class template that uses `char` as the character type.
|
||||
|
||||
#### Header
|
||||
```c++
|
||||
#include <jsoncons_ext/csv/csv_options.hpp>
|
||||
```
|
||||
|
||||
![csv_options](./diagrams/csv_options.png)
|
||||
|
||||
#### Constructors
|
||||
|
||||
csv_options()
|
||||
Constructs an `csv_options` with default values.
|
||||
|
||||
#### Modifiers
|
||||
basic_csv_options<CharT>& floating_point_format(chars_format value);
|
||||
Overrides [floating point format](../chars_format.md) when serializing csv from json. For a floating point value that was previously decoded from json text, preserves the original format when serializing.For a floating point value that was directly inserted into a json value, serializes with [chars_format::general](chars_format.md).
|
||||
|
||||
basic_csv_options<CharT>& precision(int value);
|
||||
Overrides floating point precision when serializing csv from json. The default, For a floating point value that was previously decoded from json text, preserves the original precision. The fefault, For a floating point value that was directly inserted into a json value, serializes with shortest representation.
|
||||
|
||||
basic_csv_options& header_lines(size_t value);
|
||||
Number of header lines in the CSV text. Defaults to 1 if assume_header is true, otherwise 0
|
||||
|
||||
basic_csv_options& assume_header(bool value);
|
||||
Assume first row in file is header, use field names to construct objects. Default is `false`.
|
||||
|
||||
basic_csv_options& ignore_empty_values(bool value);
|
||||
Do not read CSV fields that have empty values. Default is `false`.
|
||||
|
||||
basic_csv_options& ignore_empty_lines(bool value);
|
||||
If set to true, all lines in the file that are empty (apart from record delimiter characters) are ignored. To ignore lines with only spaces or tabs, set trim to true. Default is `true`.
|
||||
|
||||
basic_csv_options& trim_leading(bool value);
|
||||
Trim leading whitespace. Default is `false`.
|
||||
|
||||
basic_csv_options& trim_trailing(bool value);
|
||||
Trim trailing whitespace. Default is `false`.
|
||||
|
||||
basic_csv_options& trim(bool value);
|
||||
Trim both leading and trailing whitespace. Default is `false`.
|
||||
|
||||
basic_csv_options& trim_leading_inside_quotes(bool value);
|
||||
Trim leading whitespace inside quote characters. Default is `false`.
|
||||
|
||||
basic_csv_options& trim_trailing_inside_quotes(bool value);
|
||||
Trim trailing whitespace inside quote characters. Default is `false`.
|
||||
|
||||
basic_csv_options& trim_inside_quotes(bool value);
|
||||
Trim both leading and trailing whitespace inside quote characters. Default is `false`.
|
||||
|
||||
basic_csv_options& unquoted_empty_value_is_null(bool value);
|
||||
Replace empty field with json null value. Default is `false`.
|
||||
|
||||
basic_csv_options& column_names(const string_type& names);
|
||||
A comma separated list of names corresponding to the fields in the file. Example: "bool-field,float-field,string-field"
|
||||
|
||||
basic_csv_options& column_types(const string_type& types);
|
||||
A comma separated list of data types corresponding to the columns in the file. The following data types are supported: string, integer, float and boolean. Example: "bool,float,string"}
|
||||
|
||||
basic_csv_options& column_defaults(const string_type& defaults);
|
||||
A comma separated list of strings containing default json values corresponding to the columns in the file. Example: "false,0.0,"\"\""
|
||||
|
||||
basic_csv_options& field_delimiter(CharT value);
|
||||
A delimiter character that indicates the end of a field. Default is `,`
|
||||
|
||||
basic_csv_options& subfield_delimiter(CharT value);
|
||||
A delimiter character that indicates the end of a single value in a multi-valued field. Default is no multi-valued fields.
|
||||
|
||||
basic_csv_options& line_delimiter(string_type value);
|
||||
String to write between records. Default is \n.
|
||||
|
||||
basic_csv_options& quote_char(CharT value);
|
||||
Quote character. Default is quote character "
|
||||
|
||||
basic_csv_options& infer_types(bool value);
|
||||
Infer null, true, false, integers and floating point values in the CSV source. Default is `true`.
|
||||
|
||||
basic_csv_options& lossless_number(bool value);
|
||||
If set to `true`, parse numbers with exponents and fractional parts as strings with semantic tagging `semantic_tag::bigdec`. Default is `false`.
|
||||
|
||||
basic_csv_options& quote_escape_char(CharT value);
|
||||
Character to escape quote character (by default the quote character is doubled). Default is quote character `"`.
|
||||
|
||||
basic_csv_options& comment_starter(CharT value);
|
||||
Character to comment out a line, must be at column 1. Default is no comments.
|
||||
|
||||
basic_csv_options& quote_style(quote_style_type value);
|
||||
quote_style_type::all, quote_style_type::minimal, quote_style_type::none, or quote_style_type::nonnumeric. Default is quote_style_type::minimal
|
||||
|
||||
basic_csv_options& mapping(mapping_type value);
|
||||
mapping_type::n_rows, mapping_type::n_objects, mapping_type::m_columns. If assume_header is true or column_names is not empty, defaults to mapping_type::n_rows, otherwise mapping_type::n_columns.
|
||||
|
||||
basic_csv_options& max_lines(unsigned long value);
|
||||
Maximum number of lines to read. Default is unlimited.
|
||||
|
||||
#### Static member functions
|
||||
|
||||
static const basic_csv_options<CharT>& default_options()
|
||||
Default CSV encode and decode options.
|
||||
|
||||
### See also
|
||||
|
||||
[csv_decode_options](csv_decode_options.md)
|
||||
[csv_encode_options](csv_encode_options.md)
|
||||
|
|
@ -1,432 +0,0 @@
|
|||
### jsoncons::csv::csv_reader
|
||||
|
||||
```c++
|
||||
typedef basic_csv_reader<char,stream_source<char>> csv_reader
|
||||
```
|
||||
|
||||
The `csv_reader` class is an instantiation of the `basic_csv_reader` class template that uses `char` as the character type
|
||||
and `stream_source<char>` as the input source. It reads a [CSV file](http://tools.ietf.org/html/rfc4180) and produces JSON parse events.
|
||||
|
||||
`csv_reader` is noncopyable and nonmoveable.
|
||||
|
||||
#### Member types
|
||||
|
||||
Type |Definition
|
||||
---------------------------|------------------------------
|
||||
char_type |CharT
|
||||
source_type |Src
|
||||
|
||||
#### Header
|
||||
```c++
|
||||
#include <jsoncons_ext/csv/csv_reader.hpp>
|
||||
```
|
||||
#### Constructors
|
||||
|
||||
template <class Source>
|
||||
basic_csv_reader(Source&& source,
|
||||
basic_json_content_handler<CharT>& handler); // (1)
|
||||
|
||||
|
||||
template <class Source>
|
||||
basic_csv_reader(Source&& source,
|
||||
basic_json_content_handler<CharT>& handler,
|
||||
const basic_csv_options<CharT>& options); // (2)
|
||||
|
||||
template <class Source>
|
||||
basic_csv_reader(Source&& source,
|
||||
basic_json_content_handler<CharT>& handler,
|
||||
parse_error_handler& err_handler); // (3)
|
||||
|
||||
template <class Source>
|
||||
basic_csv_reader(Source&& source,
|
||||
basic_json_content_handler<CharT>& handler,
|
||||
const basic_csv_decode_options<CharT>& options,
|
||||
parse_error_handler& err_handler); // (4)
|
||||
|
||||
(1) Constructs a `csv_reader` that reads from a character sequence or stream `source`
|
||||
and a [json_content_handler](../json_content_handler.md) that receives
|
||||
JSON events. Uses default [csv_options](csv_options.md).
|
||||
|
||||
(2) Constructs a `csv_reader` that that reads from a character sequence or stream `source`, a [json_content_handler](../json_content_handler.md) that receives
|
||||
JSON events, and [csv_options](csv_options.md).
|
||||
|
||||
(3) Constructs a `csv_reader` that reads from a character sequence or stream `source`, a [json_content_handler](../json_content_handler.md) that receives
|
||||
JSON events and the specified [parse_error_handler](../parse_error_handler.md).
|
||||
Uses default [csv_options](csv_options.md).
|
||||
|
||||
(4) Constructs a `csv_reader` that reads from a character sequence or stream `source`, a [json_content_handler](../json_content_handler.md) that receives
|
||||
JSON events, [csv_options](csv_options.md),
|
||||
and the specified [parse_error_handler](../parse_error_handler.md).
|
||||
|
||||
Note: It is the programmer's responsibility to ensure that `basic_csv_reader` does not outlive any source,
|
||||
content handler, and error handler passed in the constuctor, as `basic_csv_reader` holds pointers to but does not own these resources.
|
||||
|
||||
#### Parameters
|
||||
|
||||
`source` - a value from which a `jsoncons::basic_string_view<char_type>` is constructible,
|
||||
or a value from which a `source_type` is constructible. In the case that a `jsoncons::basic_string_view<char_type>` is constructible
|
||||
from `source`, `source` is dispatched immediately to the parser. Otherwise, the `csv_reader` reads from a `source_type` in chunks.
|
||||
|
||||
#### Member functions
|
||||
|
||||
bool eof() const
|
||||
Returns `true` when there is no more data to be read from the stream, `false` otherwise
|
||||
|
||||
void read()
|
||||
Reports JSON related events for JSON objects, arrays, object members and array elements to a [json_content_handler](../json_content_handler.md), such as a [json_decoder](json_decoder.md).
|
||||
Throws [ser_error](../ser_error.md) if parsing fails.
|
||||
|
||||
size_t buffer_length() const
|
||||
|
||||
void buffer_length(size_t length)
|
||||
|
||||
### Examples
|
||||
|
||||
#### Reading a comma delimted file into an array of json values
|
||||
|
||||
#### Comma delimited input file
|
||||
```
|
||||
country_code,name
|
||||
ABW,ARUBA
|
||||
ATF,"FRENCH SOUTHERN TERRITORIES, D.R. OF"
|
||||
VUT,VANUATU
|
||||
WLF,WALLIS & FUTUNA ISLANDS
|
||||
```
|
||||
Note
|
||||
|
||||
- The first record contains a header line, but we're going to ignore that and read the entire file as an array of arrays.
|
||||
- The third record has a field value that contains an embedded comma, so it must be quoted.
|
||||
|
||||
#### Code
|
||||
```c++
|
||||
std::string in_file = "countries.csv";
|
||||
std::ifstream is(in_file);
|
||||
|
||||
json_decoder<json> decoder;
|
||||
|
||||
csv_reader reader(is,decoder);
|
||||
reader.read();
|
||||
json countries = decoder.get_result();
|
||||
|
||||
std::cout << pretty_print(countries) << std::endl;
|
||||
```
|
||||
#### Output
|
||||
```json
|
||||
[
|
||||
["country_code","name"],
|
||||
["ABW","ARUBA"],
|
||||
["ATF","FRENCH SOUTHERN TERRITORIES, D.R. OF"],
|
||||
["VUT","VANUATU"],
|
||||
["WLF","WALLIS & FUTUNA ISLANDS"]
|
||||
]
|
||||
```
|
||||
#### Reading a tab delimted file into an array of json objects
|
||||
|
||||
#### Tab delimited input file
|
||||
```
|
||||
employee-no employee-name dept salary note
|
||||
00000001 Smith, Matthew sales 150,000.00
|
||||
00000002 Brown, Sarah sales 89,000.00
|
||||
00000003 Oberc, Scott finance 110,000.00
|
||||
00000004 Scott, Colette sales 75,000.00 """Exemplary"" employee
|
||||
Dependable, trustworthy"
|
||||
```
|
||||
Note
|
||||
|
||||
- The first record is a header line, which will be used to associate data values with names
|
||||
- The fifth record has a field value that contains embedded quotes and a new line character, so it must be quoted and the embedded quotes escaped.
|
||||
|
||||
#### Code
|
||||
```c++
|
||||
std::string in_file = "employees.txt";
|
||||
std::ifstream is(in_file);
|
||||
|
||||
json_decoder<json> decoder;
|
||||
csv_options options;
|
||||
options.field_delimiter = '\t'
|
||||
.assume_header = true;
|
||||
|
||||
csv_reader reader(is,decoder,options);
|
||||
reader.read();
|
||||
json employees = decoder.get_result();
|
||||
|
||||
std::cout << pretty_print(employees) << std::endl;
|
||||
```
|
||||
|
||||
#### Output
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"dept":"sales",
|
||||
"employee-name":"Smith, Matthew",
|
||||
"employee-no":"00000001",
|
||||
"note":"",
|
||||
"salary":"150,000.00"
|
||||
},
|
||||
{
|
||||
"dept":"sales",
|
||||
"employee-name":"Brown, Sarah",
|
||||
"employee-no":"00000002",
|
||||
"note":"",
|
||||
"salary":"89,000.00"
|
||||
},
|
||||
{
|
||||
"dept":"finance",
|
||||
"employee-name":"Oberc, Scott",
|
||||
"employee-no":"00000003",
|
||||
"note":"",
|
||||
"salary":"110,000.00"
|
||||
},
|
||||
{
|
||||
"dept":"sales",
|
||||
"employee-name":"Scott, Colette",
|
||||
"employee-no":"00000004",
|
||||
"note":"\"Exemplary\" employee\nDependable, trustworthy",
|
||||
"salary":"75,000.00"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
#### Reading the comma delimited file as an array of objects with user supplied columns names
|
||||
|
||||
Note
|
||||
|
||||
- The first record contains a header line, but we're going to ignore that and use our own names for the fields.
|
||||
|
||||
#### Code
|
||||
```c++
|
||||
std::string in_file = "countries.csv";
|
||||
std::ifstream is(in_file);
|
||||
|
||||
json_decoder<json> decoder;
|
||||
|
||||
csv_options options;
|
||||
options.column_names("Country Code,Name")
|
||||
.header_lines(1);
|
||||
|
||||
csv_reader reader(is,decoder,options);
|
||||
reader.read();
|
||||
json countries = decoder.get_result();
|
||||
|
||||
std::cout << pretty_print(countries) << std::endl;
|
||||
```
|
||||
|
||||
#### Output
|
||||
```json
|
||||
[
|
||||
{
|
||||
"Country Code":"ABW",
|
||||
"Name":"ARUBA"
|
||||
},
|
||||
{
|
||||
"Country Code":"ATF",
|
||||
"Name":"FRENCH SOUTHERN TERRITORIES, D.R. OF"
|
||||
},
|
||||
{
|
||||
"Country Code":"VUT",
|
||||
"Name":"VANUATU"
|
||||
},
|
||||
{
|
||||
"Country Code":"WLF",
|
||||
"Name":"WALLIS & FUTUNA ISLANDS"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
|
||||
#### Reading a comma delimited file with different mapping options
|
||||
|
||||
#### Input
|
||||
|
||||
```csv
|
||||
Date,1Y,2Y,3Y,5Y
|
||||
2017-01-09,0.0062,0.0075,0.0083,0.011
|
||||
2017-01-08,0.0063,0.0076,0.0084,0.0112
|
||||
2017-01-08,0.0063,0.0076,0.0084,0.0112
|
||||
```
|
||||
|
||||
#### Code
|
||||
|
||||
```c++
|
||||
json_decoder<ojson> decoder;
|
||||
csv_options options;
|
||||
options.assume_header(true)
|
||||
.column_types("string,float,float,float,float");
|
||||
|
||||
options.mapping(mapping_type::n_rows);
|
||||
std::istringstream is1("bond_yields.csv");
|
||||
csv_reader reader1(is1,decoder,options);
|
||||
reader1.read();
|
||||
ojson val1 = decoder.get_result();
|
||||
std::cout << "\n(1)\n"<< pretty_print(val1) << "\n";
|
||||
|
||||
options.mapping(mapping_type::n_objects);
|
||||
std::istringstream is2("bond_yields.csv");
|
||||
csv_reader reader2(is2,decoder,options);
|
||||
reader2.read();
|
||||
ojson val2 = decoder.get_result();
|
||||
std::cout << "\n(2)\n"<< pretty_print(val2) << "\n";
|
||||
|
||||
options.mapping(mapping_type::m_columns);
|
||||
std::istringstream is3("bond_yields.csv");
|
||||
csv_reader reader3(is3, decoder, options);
|
||||
reader3.read();
|
||||
ojson val3 = decoder.get_result();
|
||||
std::cout << "\n(3)\n" << pretty_print(val3) << "\n";
|
||||
```
|
||||
|
||||
#### Output
|
||||
|
||||
```json
|
||||
(1)
|
||||
[
|
||||
["Date","1Y","2Y","3Y","5Y"],
|
||||
["2017-01-09",0.0062,0.0075,0.0083,0.011],
|
||||
["2017-01-08",0.0063,0.0076,0.0084,0.0112],
|
||||
["2017-01-08",0.0063,0.0076,0.0084,0.0112]
|
||||
]
|
||||
|
||||
(2)
|
||||
[
|
||||
{
|
||||
"Date": "2017-01-09",
|
||||
"1Y": 0.0062,
|
||||
"2Y": 0.0075,
|
||||
"3Y": 0.0083,
|
||||
"5Y": 0.011
|
||||
},
|
||||
{
|
||||
"Date": "2017-01-08",
|
||||
"1Y": 0.0063,
|
||||
"2Y": 0.0076,
|
||||
"3Y": 0.0084,
|
||||
"5Y": 0.0112
|
||||
},
|
||||
{
|
||||
"Date": "2017-01-08",
|
||||
"1Y": 0.0063,
|
||||
"2Y": 0.0076,
|
||||
"3Y": 0.0084,
|
||||
"5Y": 0.0112
|
||||
}
|
||||
]
|
||||
|
||||
(3)
|
||||
{
|
||||
"Date": ["2017-01-09","2017-01-08","2017-01-08"],
|
||||
"1Y": [0.0062,0.0063,0.0063],
|
||||
"2Y": [0.0075,0.0076,0.0076],
|
||||
"3Y": [0.0083,0.0084,0.0084],
|
||||
"5Y": [0.011,0.0112,0.0112]
|
||||
}
|
||||
```
|
||||
|
||||
#### Convert CSV to json when last column repeats
|
||||
|
||||
```c++
|
||||
int main()
|
||||
{
|
||||
const std::string bond_yields = R"(Date,Yield
|
||||
2017-01-09,0.0062,0.0075,0.0083,0.011,0.012
|
||||
2017-01-08,0.0063,0.0076,0.0084,0.0112,0.013
|
||||
2017-01-08,0.0063,0.0076,0.0084,0.0112,0.014
|
||||
)";
|
||||
|
||||
// array of arrays
|
||||
json_decoder<ojson> decoder1;
|
||||
csv_options options1;
|
||||
options1.header_lines(1);
|
||||
options1.assume_header(false);
|
||||
options1.column_types("string,float*");
|
||||
std::istringstream is1(bond_yields);
|
||||
csv_reader reader1(is1, decoder1, options1);
|
||||
reader1.read();
|
||||
ojson val1 = decoder1.get_result();
|
||||
std::cout << "\n(1)\n" << pretty_print(val1) << "\n";
|
||||
|
||||
// array of objects
|
||||
json_decoder<ojson> decoder2;
|
||||
csv_options options2;
|
||||
options2.assume_header(true);
|
||||
options2.column_types("string,[float*]");
|
||||
std::istringstream is2(bond_yields);
|
||||
csv_reader reader2(is2, decoder2, options2);
|
||||
reader2.read();
|
||||
ojson val2 = decoder2.get_result();
|
||||
std::cout << "\n(2)\n" << pretty_print(val2) << "\n";
|
||||
}
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
(1)
|
||||
[
|
||||
["2017-01-09",0.0062,0.0075,0.0083,0.011,0.012],
|
||||
["2017-01-08",0.0063,0.0076,0.0084,0.0112,0.013],
|
||||
["2017-01-08",0.0063,0.0076,0.0084,0.0112,0.014]
|
||||
]
|
||||
|
||||
(2)
|
||||
[
|
||||
{
|
||||
"Date": "2017-01-09",
|
||||
"Yield": [0.0062,0.0075,0.0083,0.011,0.012]
|
||||
},
|
||||
{
|
||||
"Date": "2017-01-08",
|
||||
"Yield": [0.0063,0.0076,0.0084,0.0112,0.013]
|
||||
},
|
||||
{
|
||||
"Date": "2017-01-08",
|
||||
"Yield": [0.0063,0.0076,0.0084,0.0112,0.014]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
#### Convert CSV to json when last two columns repeat
|
||||
|
||||
```c++
|
||||
const std::string holidays = R"(1,CAD,2,UK,3,EUR,4,US + UK,5,US
|
||||
38719,2-Jan-2006,40179,1-Jan-2010,38719,2-Jan-2006,38719,2-Jan-2006,39448,1-Jan-2008
|
||||
38733,16-Jan-2006,40270,2-Apr-2010,38733,16-Jan-2006,38733,16-Jan-2006,39468,21-Jan-2008
|
||||
)";
|
||||
|
||||
json_decoder<ojson> decoder;
|
||||
csv_options options;
|
||||
options.column_types("[integer,string]*");
|
||||
|
||||
// Default
|
||||
std::istringstream is1(holidays);
|
||||
csv_reader reader1(is1, decoder, options);
|
||||
reader1.read();
|
||||
ojson val1 = decoder.get_result();
|
||||
std::cout << pretty_print(val1) << "\n";
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
[
|
||||
[
|
||||
[1,"CAD"],
|
||||
[2,"UK"],
|
||||
[3,"EUR"],
|
||||
[4,"US + UK"],
|
||||
[5,"US"]
|
||||
],
|
||||
[
|
||||
[38719,"2-Jan-2006"],
|
||||
[40179,"1-Jan-2010"],
|
||||
[38719,"2-Jan-2006"],
|
||||
[38719,"2-Jan-2006"],
|
||||
[39448,"1-Jan-2008"]
|
||||
],
|
||||
[
|
||||
[38733,"16-Jan-2006"],
|
||||
[40270,"2-Apr-2010"],
|
||||
[38733,"16-Jan-2006"],
|
||||
[38733,"16-Jan-2006"],
|
||||
[39468,"21-Jan-2008"]
|
||||
]
|
||||
]
|
||||
```
|
|
@ -1,338 +0,0 @@
|
|||
### jsoncons::csv::decode_csv
|
||||
|
||||
Decodes a [comma-separated variables (CSV)](https://en.wikipedia.org/wiki/Comma-separated_values) data format into a C++ data structure.
|
||||
|
||||
#### Header
|
||||
```c++
|
||||
#include <jsoncons_ext/csv/csv_reader.hpp>
|
||||
|
||||
template <class T,class CharT>
|
||||
T decode_csv(const std::basic_string<CharT>& s,
|
||||
const basic_csv_options<CharT>& options = basic_csv_options<CharT>::default_options())); // (1)
|
||||
|
||||
template <class T,class CharT>
|
||||
T decode_csv(std::basic_istream<CharT>& is,
|
||||
const basic_csv_options<CharT>& options = basic_csv_options<CharT>::default_options())); // (2)
|
||||
```
|
||||
|
||||
(1) Reads a CSV string value into a type T if T is an instantiation of [basic_json](../json.md)
|
||||
or if T supports [json_type_traits](../json_type_traits.md).
|
||||
|
||||
(2) Reads a CSV input stream into a type T if T is an instantiation of [basic_json](../json.md)
|
||||
or if T supports [json_type_traits](../json_type_traits.md).
|
||||
|
||||
#### Return value
|
||||
|
||||
Returns a value of type `T`.
|
||||
|
||||
#### Exceptions
|
||||
|
||||
Throws [ser_error](ser_error.md) if parsing fails.
|
||||
|
||||
### Examples
|
||||
|
||||
#### Decode a CSV file with type inference (default)
|
||||
|
||||
Example file (sales.csv)
|
||||
```csv
|
||||
customer_name,has_coupon,phone_number,zip_code,sales_tax_rate,total_amount
|
||||
"John Roe",true,0272561313,01001,0.05,431.65
|
||||
"Jane Doe",false,416-272-2561,55416,0.15,480.70
|
||||
"Joe Bloggs",false,"4162722561","55416",0.15,300.70
|
||||
"John Smith",FALSE,NULL,22313-1450,0.15,300.70
|
||||
```
|
||||
|
||||
```c++
|
||||
#include <fstream>
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons_ext/csv/csv_reader.hpp>
|
||||
|
||||
using namespace jsoncons;
|
||||
|
||||
int main()
|
||||
{
|
||||
csv::csv_options options;
|
||||
options.assume_header(true);
|
||||
|
||||
options.mapping(csv::mapping_type::n_objects);
|
||||
std::ifstream is1("input/sales.csv");
|
||||
ojson j1 = csv::decode_csv<ojson>(is1,options);
|
||||
std::cout << "\n(1)\n"<< pretty_print(j1) << "\n";
|
||||
|
||||
options.mapping(csv::mapping_type::n_rows);
|
||||
std::ifstream is2("input/sales.csv");
|
||||
ojson j2 = csv::decode_csv<ojson>(is2,options);
|
||||
std::cout << "\n(2)\n"<< pretty_print(j2) << "\n";
|
||||
|
||||
options.mapping(csv::mapping_type::m_columns);
|
||||
std::ifstream is3("input/sales.csv");
|
||||
ojson j3 = csv::decode_csv<ojson>(is3,options);
|
||||
std::cout << "\n(3)\n"<< pretty_print(j3) << "\n";
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```json
|
||||
(1)
|
||||
[
|
||||
{
|
||||
"customer_name": "John Roe",
|
||||
"has_coupon": true,
|
||||
"phone_number": "0272561313",
|
||||
"zip_code": "01001",
|
||||
"sales_tax_rate": 0.05,
|
||||
"total_amount": 431.65
|
||||
},
|
||||
{
|
||||
"customer_name": "Jane Doe",
|
||||
"has_coupon": false,
|
||||
"phone_number": "416-272-2561",
|
||||
"zip_code": 55416,
|
||||
"sales_tax_rate": 0.15,
|
||||
"total_amount": 480.7
|
||||
},
|
||||
{
|
||||
"customer_name": "Joe Bloggs",
|
||||
"has_coupon": false,
|
||||
"phone_number": "4162722561",
|
||||
"zip_code": "55416",
|
||||
"sales_tax_rate": 0.15,
|
||||
"total_amount": 300.7
|
||||
},
|
||||
{
|
||||
"customer_name": "John Smith",
|
||||
"has_coupon": false,
|
||||
"phone_number": null,
|
||||
"zip_code": "22313-1450",
|
||||
"sales_tax_rate": 0.15,
|
||||
"total_amount": 300.7
|
||||
}
|
||||
]
|
||||
|
||||
(2)
|
||||
[
|
||||
["customer_name","has_coupon","phone_number","zip_code","sales_tax_rate","total_amount"],
|
||||
["John Roe",true,"0272561313","01001",0.05,431.65],
|
||||
["Jane Doe",false,"416-272-2561",55416,0.15,480.7],
|
||||
["Joe Bloggs",false,"4162722561","55416",0.15,300.7],
|
||||
["John Smith",false,null,"22313-1450",0.15,300.7]
|
||||
]
|
||||
|
||||
(3)
|
||||
{
|
||||
"customer_name": ["John Roe","Jane Doe","Joe Bloggs","John Smith"],
|
||||
"has_coupon": [true,false,false,false],
|
||||
"phone_number": ["0272561313","416-272-2561",4162722561,null],
|
||||
"zip_code": ["01001",55416,55416,"22313-1450"],
|
||||
"sales_tax_rate": [0.05,0.15,0.15,0.15],
|
||||
"total_amount": [431.65,480.7,300.7,300.7]
|
||||
}
|
||||
```
|
||||
|
||||
#### Decode a CSV string without type inference
|
||||
|
||||
```c++
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons_ext/csv/csv_reader.hpp>
|
||||
|
||||
using namespace jsoncons;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::string s = R"(employee-no,employee-name,dept,salary
|
||||
00000001,"Smith,Matthew",sales,150000.00
|
||||
00000002,"Brown,Sarah",sales,89000.00
|
||||
)";
|
||||
|
||||
csv::csv_options options;
|
||||
options.assume_header(true)
|
||||
.infer_types(false);
|
||||
ojson j = csv::decode_csv<ojson>(s,options);
|
||||
|
||||
std::cout << pretty_print(j) << std::endl;
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```json
|
||||
[
|
||||
{
|
||||
"employee-no": "00000001",
|
||||
"employee-name": "Smith,Matthew",
|
||||
"dept": "sales",
|
||||
"salary": "150000.00"
|
||||
},
|
||||
{
|
||||
"employee-no": "00000002",
|
||||
"employee-name": "Brown,Sarah",
|
||||
"dept": "sales",
|
||||
"salary": "89000.00"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
#### Decode a CSV string with specified types
|
||||
|
||||
```c++
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons_ext/csv/csv_reader.hpp>
|
||||
|
||||
using namespace jsoncons;
|
||||
|
||||
int main()
|
||||
{
|
||||
const std::string s = R"(Date,1Y,2Y,3Y,5Y
|
||||
2017-01-09,0.0062,0.0075,0.0083,0.011
|
||||
2017-01-08,0.0063,0.0076,0.0084,0.0112
|
||||
2017-01-08,0.0063,0.0076,0.0084,0.0112
|
||||
)";
|
||||
|
||||
csv::csv_options options;
|
||||
options.assume_header(true)
|
||||
.column_types("string,float,float,float,float");
|
||||
|
||||
// mapping_type::n_objects
|
||||
options.mapping(csv::mapping_type::n_objects);
|
||||
ojson j1 = csv::decode_csv<ojson>(s,options);
|
||||
std::cout << "\n(1)\n"<< pretty_print(j1) << "\n";
|
||||
|
||||
// mapping_type::n_rows
|
||||
options.mapping(csv::mapping_type::n_rows);
|
||||
ojson j2 = csv::decode_csv<ojson>(s,options);
|
||||
std::cout << "\n(2)\n"<< pretty_print(j2) << "\n";
|
||||
|
||||
// mapping_type::m_columns
|
||||
options.mapping(csv::mapping_type::m_columns);
|
||||
ojson j3 = csv::decode_csv<ojson>(s,options);
|
||||
std::cout << "\n(3)\n" << pretty_print(j3) << "\n";
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```json
|
||||
(1)
|
||||
[
|
||||
{
|
||||
"Date": "2017-01-09",
|
||||
"1Y": 0.0062,
|
||||
"2Y": 0.0075,
|
||||
"3Y": 0.0083,
|
||||
"5Y": 0.011
|
||||
},
|
||||
{
|
||||
"Date": "2017-01-08",
|
||||
"1Y": 0.0063,
|
||||
"2Y": 0.0076,
|
||||
"3Y": 0.0084,
|
||||
"5Y": 0.0112
|
||||
},
|
||||
{
|
||||
"Date": "2017-01-08",
|
||||
"1Y": 0.0063,
|
||||
"2Y": 0.0076,
|
||||
"3Y": 0.0084,
|
||||
"5Y": 0.0112
|
||||
}
|
||||
]
|
||||
|
||||
(2)
|
||||
[
|
||||
["Date","1Y","2Y","3Y","5Y"],
|
||||
["2017-01-09",0.0062,0.0075,0.0083,0.011],
|
||||
["2017-01-08",0.0063,0.0076,0.0084,0.0112],
|
||||
["2017-01-08",0.0063,0.0076,0.0084,0.0112]
|
||||
]
|
||||
|
||||
(3)
|
||||
{
|
||||
"Date": ["2017-01-09","2017-01-08","2017-01-08"],
|
||||
"1Y": [0.0062,0.0063,0.0063],
|
||||
"2Y": [0.0075,0.0076,0.0076],
|
||||
"3Y": [0.0083,0.0084,0.0084],
|
||||
"5Y": [0.011,0.0112,0.0112]
|
||||
}
|
||||
```
|
||||
#### Decode a CSV string with multi-valued fields separated by subfield delimiters
|
||||
|
||||
```c++
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons_ext/csv/csv_reader.hpp>
|
||||
|
||||
using namespace jsoncons;
|
||||
|
||||
int main()
|
||||
{
|
||||
const std::string s = R"(calculationPeriodCenters,paymentCenters,resetCenters
|
||||
NY;LON,TOR,LON
|
||||
NY,LON,TOR;LON
|
||||
"NY";"LON","TOR","LON"
|
||||
"NY","LON","TOR";"LON"
|
||||
)";
|
||||
json_options print_options;
|
||||
print_options.array_array_line_splits(line_split_kind::same_line);
|
||||
|
||||
csv::csv_options options1;
|
||||
options1.assume_header(true)
|
||||
.subfield_delimiter(';');
|
||||
|
||||
json j1 = csv::decode_csv<json>(s,options1);
|
||||
std::cout << "(1)\n" << pretty_print(j1,print_options) << "\n\n";
|
||||
|
||||
csv::csv_options options2;
|
||||
options2.mapping(csv::mapping_type::n_rows)
|
||||
.subfield_delimiter(';');
|
||||
|
||||
json j2 = csv::decode_csv<json>(s,options2);
|
||||
std::cout << "(2)\n" << pretty_print(j2,print_options) << "\n\n";
|
||||
|
||||
csv::csv_options options3;
|
||||
options3.assume_header(true)
|
||||
.mapping(csv::mapping_type::m_columns)
|
||||
.subfield_delimiter(';');
|
||||
|
||||
json j3 = csv::decode_csv<json>(s,options3);
|
||||
std::cout << "(3)\n" << pretty_print(j3,print_options) << "\n\n";
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```json
|
||||
(1)
|
||||
[
|
||||
|
||||
{
|
||||
"calculationPeriodCenters": ["NY","LON"],
|
||||
"paymentCenters": "TOR",
|
||||
"resetCenters": "LON"
|
||||
},
|
||||
{
|
||||
"calculationPeriodCenters": "NY",
|
||||
"paymentCenters": "LON",
|
||||
"resetCenters": ["TOR","LON"]
|
||||
},
|
||||
{
|
||||
"calculationPeriodCenters": ["NY","LON"],
|
||||
"paymentCenters": "TOR",
|
||||
"resetCenters": "LON"
|
||||
},
|
||||
{
|
||||
"calculationPeriodCenters": "NY",
|
||||
"paymentCenters": "LON",
|
||||
"resetCenters": ["TOR","LON"]
|
||||
}
|
||||
]
|
||||
|
||||
(2)
|
||||
[
|
||||
|
||||
["calculationPeriodCenters","paymentCenters","resetCenters"],
|
||||
[["NY","LON"],"TOR","LON"],
|
||||
["NY","LON",["TOR","LON"]],
|
||||
[["NY","LON"],"TOR","LON"],
|
||||
["NY","LON",["TOR","LON"]]
|
||||
]
|
||||
|
||||
(3)
|
||||
{
|
||||
"calculationPeriodCenters": [["NY","LON"],"NY",["NY","LON"],"NY"],
|
||||
"paymentCenters": ["TOR","LON","TOR","LON"],
|
||||
"resetCenters": ["LON",["TOR","LON"],"LON",["TOR","LON"]]
|
||||
}
|
||||
```
|
||||
|
Before Width: | Height: | Size: 5.1 KiB |
|
@ -1 +0,0 @@
|
|||
<mxfile modified="2019-03-29T03:27:22.248Z" host="www.draw.io" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36" etag="Jrzm1AiD0JSzdItezCxt" version="10.5.9" type="device"><diagram id="iK-0d-7Yl-5MlnfMu26I" name="Page-1">vVZdb9owFP01eeyUxIXSxxZot6FW65gEfUJufJt4c2zmGAj79bOJTeIkqFSq2ofK91xff5xzrkOAxnl5L/E6exAEWBCHpAzQJIjjq2ik/xtgXwFoGFZAKimpoKgG5vQfWNBN21AChTdRCcEUXftgIjiHRHkYllLs/Gmvgvm7rnEKHWCeYNZFF5SorEJHg7DGvwJNM7dzFNpMjt1kCxQZJmLXgNA0QGMphKpGeTkGZrhzvFR1dyeyx4NJ4Oqcgunjr5LPnuZZPP47U4uH/Ln8fmFX2WK2sRd+wQVNVr8LwVeaU6UXX2WYEwYyiIdM73T7YkapGfUhh6uqveNPig0nYI4Q6vQuowrma5yY7E4bRmOZypmOomN180rufCAVlA3IXvEeRA5K7vUUmx1Ztq3dIsf+rhYvchbMGsJdWgxbv6THlWtK9cCy+g6Gr04wnBTbFfBE98snEPtKGRsLJuShFsHhT+OFkuIPNDJoiK4R+RgpztJi8JlajDpadGgFTm7Ms6GjhOFCK+UzCSVVS0u6GT+b8ZeBjSZlIzXZu4Drwy/dAiZoVJmwLjtEru6kBoXYyATeNp3CMgX1dvsD8R7BrqINxfoEc5gEhhXd+k9nn4p2hx+C6psdDXPp+yVGLR9U17ZFzZeutc51y3ej1joVLZ11DpY6Xvosl6XbhyyePS7xT0gvFk8z2M6gp+O/8QwkVZhr0fSnkOJU4rxjPd1Wyjeb355ccGj1soUwoyk3jtVG0c8JujVNSvVH7MYmckqI2ab3nfBfko9o/LAlZNjT+KjHR/H7G1+H9Se0UrD+HYKm/wE=</diagram></mxfile>
|
Before Width: | Height: | Size: 6.2 KiB |
|
@ -1 +0,0 @@
|
|||
<mxfile modified="2019-04-08T16:01:07.146Z" host="www.draw.io" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36" etag="DDZLvg8Hk96CLs5A0ssZ" version="10.6.0" type="device"><diagram id="aNkMF165W3cufMvMLNcI" name="Page-1">zZbJbtswEIafRscWWurl2thZDm1R1ECbngRGHEtEKVGhKEvq05eMhlqdOA2M1heD85MzJL/5TcgJNml9K0mefBYUuOO7tHaCreP7q0Wgf43QtEKw9Fohloy20kDYsd+AootqySgUo4VKCK5YPhYjkWUQqZFGpBTVeNle8PGuOYlhJuwiwufqD0ZV0qrrhdvrd8DixO7suTiTErsYhSIhVFQDKbh2go0UQrWjtN4AN+wslzbv5pnZ7mASMvWahP33Zv8t/3X3KL6Ej+twe1V+at5hlQPhJV74gRQsCqPiEFKIdDdDkSsmsgIvoRpLRooyo2CKu05wVSVMwS4nkZmttBW0lqiU68jTw/lh7c4gFdQDCQ9/CyIFJRu9BGc/IEc00hrDqu+Kt0QtGXTEphE0QtwV7lnpAeL6C3T+C+ggu2R0Haf/xi54gd2lQPOXE2r+EWr+v6S2nFGbQYKMfjSvno4iTgrNdMwFaqbuEaEZ/zTj9wuMtvVgatvYINOHv7cFTDDIMmGf9hTZvGd7UIhSRnDaHorIGNTpvyDQ0Rs+7+igY4sjDbOaBE4UO4xf/mNdxB2+CqZv1hmmM0MzMZAt0d4bs4Yv9bTQalLImxRqwcwKPZmqu/bbfbY6g8/O7ZmTXvAuyguzx2P6KLzWC+uJFfxzWUGH/bdHu7z/gAuu/wA=</diagram></mxfile>
|
|
@ -1,71 +0,0 @@
|
|||
### jsoncons::csv::encode_csv
|
||||
|
||||
Encodes a C++ data structure into the CSV data format.
|
||||
|
||||
#### Header
|
||||
```c++
|
||||
#include <jsoncons_ext/csv/csv_encoder.hpp>
|
||||
|
||||
template <class T,class CharT>
|
||||
void encode_csv(const T& val,
|
||||
std::basic_string<CharT>& s,
|
||||
const basic_csv_options<CharT>& options = basic_csv_options<CharT>::default_options())); // (1)
|
||||
|
||||
template <class T, class CharT>
|
||||
void encode_csv(const T& val,
|
||||
std::basic_ostream<CharT>& os,
|
||||
const basic_csv_options<CharT>& options = basic_csv_options<CharT>::default_options())); // (2)
|
||||
```
|
||||
|
||||
(1) Writes a value of type T into a string in the CSV data format. Type T must be an instantiation of [basic_json](../json.md)
|
||||
or support [json_type_traits](../json_type_traits.md). Uses the [encode options](csv_options.md)
|
||||
supplied or defaults.
|
||||
|
||||
(2) Writes a value of type T into an output stream in the CSV data format. Type T must be an instantiation of [basic_json](../json.md)
|
||||
or support [json_type_traits](../json_type_traits.md). Uses the [encode options](csv_options.md)
|
||||
supplied or defaults.
|
||||
|
||||
### Examples
|
||||
|
||||
#### Write a json value to a CSV output stream
|
||||
|
||||
```c++
|
||||
#include <iostream>
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons_ext/csv/csv_encoder.hpp>
|
||||
|
||||
using namespace jsoncons;
|
||||
|
||||
int main()
|
||||
{
|
||||
const json books = json::parse(R"(
|
||||
[
|
||||
{
|
||||
"title" : "Kafka on the Shore",
|
||||
"author" : "Haruki Murakami",
|
||||
"price" : 25.17
|
||||
},
|
||||
{
|
||||
"title" : "Women: A Novel",
|
||||
"author" : "Charles Bukowski",
|
||||
"price" : 12.00
|
||||
},
|
||||
{
|
||||
"title" : "Cutter's Way",
|
||||
"author" : "Ivan Passer"
|
||||
}
|
||||
]
|
||||
)");
|
||||
|
||||
csv::encode_csv(books, std::cout);
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```json
|
||||
author,price,title
|
||||
Haruki Murakami,00,Kafka on the Shore
|
||||
Charles Bukowski,00,Women: A Novel
|
||||
Ivan Passer,,Cutter's Way
|
||||
```
|
||||
|
||||
|
|
@ -1,209 +0,0 @@
|
|||
## jsoncons data model
|
||||
|
||||
The jsoncons data model supports the familiar JSON types - nulls,
|
||||
booleans, numbers, strings, arrays, objects - plus byte strings. It has
|
||||
|
||||
- null
|
||||
- bool
|
||||
- int64
|
||||
- uint64
|
||||
- double
|
||||
- string
|
||||
- byte string
|
||||
- array
|
||||
- object
|
||||
|
||||
In addition, jsoncons supports semantic tagging of date-time values, timestamp values, big integers,
|
||||
big decimals, bigfloats and binary encodings. This allows it to preserve these type semantics when parsing
|
||||
JSON-like data formats such as CBOR that have them, for example, the mappings between the jsoncons
|
||||
and CBOR data items are shown below:
|
||||
|
||||
jsoncons data item|jsoncons tag|CBOR data item|CBOR tag
|
||||
--------------|------------------|---------------|--------
|
||||
null | | null | 
|
||||
null | undefined | undefined | 
|
||||
bool | | true or false | 
|
||||
int64 | | unsigned or negative integer | 
|
||||
int64 | timestamp | unsigned or negative integer | 1 (epoch-based date/time)
|
||||
uint64 | | unsigned integer | 
|
||||
uint64 | timestamp | unsigned integer | 1 (epoch-based date/time)
|
||||
double | | half-precision float, float, or double | 
|
||||
double | timestamp | double | 1 (epoch-based date/time)
|
||||
string | | string | 
|
||||
string | bigint | byte string | 2 (positive bignum) or 2 (negative bignum)
|
||||
string | bigdec | array | 4 (decimal fraction)
|
||||
string | bigfloat | array | 5 (bigfloat)
|
||||
string | datetime | string | 0 (date/time string)
|
||||
string | uri | string | 32 (uri)
|
||||
string | base64url | string | 33 (base64url)
|
||||
string | base64 | string | 34 (base64)
|
||||
byte_string | | byte string | 
|
||||
byte_string | base64url | byte string | 21 (Expected conversion to base64url encoding)
|
||||
byte_string | base64 | byte string | 22 (Expected conversion to base64 encoding)
|
||||
byte_string | base16 | byte string | 23 (Expected conversion to base16 encoding)
|
||||
array | | array | 
|
||||
object | | map | 
|
||||
|
||||
### Examples
|
||||
|
||||
#### json value to CBOR item
|
||||
|
||||
```c++
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons_ext/cbor/cbor.hpp>
|
||||
|
||||
using namespace jsoncons;
|
||||
|
||||
int main()
|
||||
{
|
||||
json j = json::array();
|
||||
|
||||
j.emplace_back("foo");
|
||||
j.emplace_back(byte_string{ 'b','a','r' });
|
||||
j.emplace_back("-18446744073709551617", semantic_tag::bigint);
|
||||
j.emplace_back("273.15", semantic_tag::bigdec);
|
||||
j.emplace_back("2018-10-19 12:41:07-07:00", semantic_tag::datetime);
|
||||
j.emplace_back(1431027667, semantic_tag::timestamp);
|
||||
j.emplace_back(-1431027667, semantic_tag::timestamp);
|
||||
j.emplace_back(1431027667.5, semantic_tag::timestamp);
|
||||
|
||||
std::cout << "(1)\n" << pretty_print(j) << "\n\n";
|
||||
|
||||
std::vector<uint8_t> bytes;
|
||||
cbor::encode_cbor(j, bytes);
|
||||
std::cout << "(2)\n";
|
||||
for (auto c : bytes)
|
||||
{
|
||||
std::cout << std::hex << std::noshowbase << std::setprecision(2) << std::setw(2)
|
||||
<< std::setfill('0') << static_cast<int>(c);
|
||||
}
|
||||
std::cout << "\n\n";
|
||||
/*
|
||||
88 -- Array of length 8
|
||||
63 -- String value of length 3
|
||||
666f6f -- "foo"
|
||||
43 -- Byte string value of length 3
|
||||
626172 -- 'b''a''r'
|
||||
c3 -- Tag 3 (negative bignum)
|
||||
49 Byte string value of length 9
|
||||
010000000000000000 -- Bytes content
|
||||
c4 - Tag 4 (decimal fraction)
|
||||
82 -- Array of length 2
|
||||
21 -- -2
|
||||
19 6ab3 -- 27315
|
||||
c0 -- Tag 0 (date-time)
|
||||
78 19 -- Length (25)
|
||||
323031382d31302d31392031323a34313a30372d30373a3030 -- "2018-10-19 12:41:07-07:00"
|
||||
c1 -- Tag 1 (epoch time)
|
||||
1a -- uint32_t
|
||||
554bbfd3 -- 1431027667
|
||||
c1
|
||||
3a
|
||||
554bbfd2
|
||||
c1
|
||||
fb
|
||||
41d552eff4e00000
|
||||
*/
|
||||
}
|
||||
```
|
||||
Output
|
||||
```
|
||||
(1)
|
||||
[
|
||||
"foo",
|
||||
"YmFy",
|
||||
"-18446744073709551617",
|
||||
"273.15",
|
||||
"2018-10-19 12:41:07-07:00",
|
||||
1431027667,
|
||||
-1431027667,
|
||||
1431027667.5
|
||||
]
|
||||
|
||||
(2)
|
||||
8863666f6f43626172c349010000000000000000c48221196ab3c07819323031382d31302d31392031323a34313a30372d30373a3030c11a554bbfd3c13a554bbfd2c1fb41d552eff4e00000
|
||||
```
|
||||
|
||||
#### CBOR item to json value
|
||||
|
||||
```c++
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons_ext/cbor/cbor.hpp>
|
||||
|
||||
using namespace jsoncons;
|
||||
|
||||
void main()
|
||||
{
|
||||
std::vector<uint8_t> bytes;
|
||||
cbor::cbor_bytes_encoder encoder(bytes);
|
||||
encoder.begin_array(); // indefinite length outer array
|
||||
encoder.string_value("foo");
|
||||
encoder.byte_string_value(byte_string({'b','a','r'}));
|
||||
encoder.string_value("-18446744073709551617", semantic_tag::bigint);
|
||||
encoder.decimal_value("273.15");
|
||||
encoder.string_value("2018-10-19 12:41:07-07:00", semantic_tag::datetime) ;
|
||||
encoder.epoch_time_value(1431027667);
|
||||
encoder.int64_value(-1431027667, semantic_tag::timestamp);
|
||||
encoder.double_value(1431027667.5, semantic_tag::timestamp);
|
||||
encoder.end_array();
|
||||
encoder.flush();
|
||||
|
||||
std::cout << "(1)\n";
|
||||
for (auto c : bytes)
|
||||
{
|
||||
std::cout << std::hex << std::noshowbase << std::setprecision(2) << std::setw(2)
|
||||
<< std::setfill('0') << static_cast<int>(c);
|
||||
}
|
||||
std::cout << "\n\n";
|
||||
|
||||
/*
|
||||
9f -- Start indefinite length array
|
||||
63 -- String value of length 3
|
||||
666f6f -- "foo"
|
||||
43 -- Byte string value of length 3
|
||||
626172 -- 'b''a''r'
|
||||
c3 -- Tag 3 (negative bignum)
|
||||
49 Byte string value of length 9
|
||||
010000000000000000 -- Bytes content
|
||||
c4 - Tag 4 (decimal fraction)
|
||||
82 -- Array of length 2
|
||||
21 -- -2
|
||||
19 6ab3 -- 27315
|
||||
c0 -- Tag 0 (date-time)
|
||||
78 19 -- Length (25)
|
||||
323031382d31302d31392031323a34313a30372d30373a3030 -- "2018-10-19 12:41:07-07:00"
|
||||
c1 -- Tag 1 (epoch time)
|
||||
1a -- uint32_t
|
||||
554bbfd3 -- 1431027667
|
||||
c1
|
||||
3a
|
||||
554bbfd2
|
||||
c1
|
||||
fb
|
||||
41d552eff4e00000
|
||||
ff -- "break"
|
||||
*/
|
||||
|
||||
json j = cbor::decode_cbor<json>(bytes);
|
||||
|
||||
std::cout << "(2)\n" << pretty_print(j) << "\n\n";
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```
|
||||
(1)
|
||||
9f63666f6f43626172c349010000000000000000c48221196ab3c07819323031382d31302d31392031323a34313a30372d30373a3030c11a554bbfd3c13a554bbfd2c1fb41d552eff4e00000ff
|
||||
|
||||
(2)
|
||||
[
|
||||
"foo",
|
||||
"YmFy",
|
||||
"-18446744073709551617",
|
||||
"273.15",
|
||||
"2018-10-19 12:41:07-07:00",
|
||||
1431027667,
|
||||
-1431027667,
|
||||
1431027667.5
|
||||
]
|
||||
```
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
### jsoncons::decode_json
|
||||
|
||||
Decodes a JSON data format to a C++ data structure. `decode_json` will
|
||||
work for all C++ classes that have [json_type_traits](https://github.com/danielaparker/jsoncons/blob/master/doc/ref/json_type_traits.md) defined.
|
||||
|
||||
#### Header
|
||||
|
||||
```c++
|
||||
#include <jsoncons/json.hpp>
|
||||
|
||||
template <class T, class CharT>
|
||||
T decode_json(std::basic_istream<CharT>& is,
|
||||
const basic_json_decode_options<CharT>& options = basic_json_options<CharT>::default_options()); // (1)
|
||||
|
||||
template <class T, class CharT>
|
||||
T decode_json(const std::basic_string<CharT>& s,
|
||||
const basic_json_decode_options<CharT>& options = basic_json_options<CharT>::default_options()); // (2)
|
||||
|
||||
|
||||
template <class T, class CharT, class ImplementationPolicy, class Allocator>
|
||||
T decode_json(const basic_json<CharT,ImplementationPolicy,Allocator>& j,
|
||||
std::basic_istream<CharT>& is,
|
||||
const basic_json_decode_options<CharT>& options = basic_json_options<CharT>::default_options()); // (3)
|
||||
|
||||
template <class T, class CharT, class ImplementationPolicy, class Allocator>
|
||||
T decode_json(const basic_json<CharT,ImplementationPolicy,Allocator>& j,
|
||||
const std::basic_string<CharT>& s,
|
||||
const basic_json_decode_options<CharT>& options = basic_json_options<CharT>::default_options()); // (4)
|
||||
```
|
||||
|
||||
(1) Reads a JSON string value into a type T if T is an instantiation of [basic_json](../json.md)
|
||||
or if T supports [json_type_traits](../json_type_traits.md).
|
||||
|
||||
(2) Reads a JSON input stream into a type T if T is an instantiation of [basic_json](../json.md)
|
||||
or if T supports [json_type_traits](../json_type_traits.md).
|
||||
|
||||
Functions (1)-(2) perform encodings using the default json type `basic_json<CharT>`.
|
||||
Functions (3)-(4) are the same but perform encodings using the supplied `basic_json`.
|
||||
|
||||
### Examples
|
||||
|
||||
#### Map with string-tuple pairs
|
||||
|
||||
```c++
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <tuple>
|
||||
#include <jsoncons/json.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
typedef std::map<std::string,std::tuple<std::string,std::string,double>> employee_collection;
|
||||
|
||||
std::string s = R"(
|
||||
{
|
||||
"Jane Doe": ["Commission","Sales",20000.0],
|
||||
"John Smith": ["Hourly","Software Engineer",10000.0]
|
||||
}
|
||||
)";
|
||||
|
||||
employee_collection employees = jsoncons::decode_json<employee_collection>(s);
|
||||
|
||||
for (const auto& pair : employees)
|
||||
{
|
||||
std::cout << pair.first << ": " << std::get<1>(pair.second) << std::endl;
|
||||
}
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```
|
||||
Jane Doe: Sales
|
||||
John Smith: Software Engineer
|
||||
```
|
||||
|
||||
#### See also
|
||||
|
||||
- [encode_json](encode_json.md)
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
### jsoncons::default_parse_error_handler
|
||||
|
||||
```c++
|
||||
class default_parse_error_handler;
|
||||
```
|
||||
|
||||
#### Header
|
||||
|
||||
#include <jsoncons/parse_error_handler.hpp>
|
||||
|
||||
#### Base class
|
||||
|
||||
[parse_error_handler](parse_error_handler.md)
|
||||
|
||||
##### Private virtual implementation methods
|
||||
|
||||
bool do_error(std::error_code ec, const ser_context& context) override;
|
||||
|
||||
Returns `true` if `ec` indicates a comment, otherwise `false`
|
||||
|
||||
|
|
@ -1,110 +0,0 @@
|
|||
## Deprecated Features
|
||||
|
||||
As the `jsoncons` library has evolved, names have sometimes changed. To ease transition, jsoncons deprecates the old names but continues to support many of them. The deprecated names can be suppressed by defining macro JSONCONS_NO_DEPRECATED, which is recommended for new code.
|
||||
|
||||
In the table, <em>✓</em> indicates that the old name is still supported.
|
||||
|
||||
Component or location|Old name, now deprecated|<em>✓</em>|New name
|
||||
--------|-----------|--------------|------------------------
|
||||
class parse_error|`parse_error`|<em>✓</em>|`serialization_error`
|
||||
class basic_json|`object_iterator`|<em>✓</em>|`object_iterator_type`
|
||||
class basic_json|`const_object_iterator`|<em>✓</em>|`const_object_iterator_type`
|
||||
class basic_json|`array_iterator`|<em>✓</em>|`array_iterator_type`
|
||||
class basic_json|`const_array_iterator`|<em>✓</em>|`const_array_iterator_type`
|
||||
class basic_json|add(size_t index, const json& val)|<em>✓</em>|`insert(array_iterator pos, const json& val)`
|
||||
class basic_json|add(size_t index, json&& val)|<em>✓</em>|`insert(array_iterator pos, json&& val)`
|
||||
class basic_json|dump_body|<em>✓</em>|`dump`
|
||||
class basic_json|remove_range(size_t from_index, size_t to_index)|<em>✓</em>|`erase(array_iterator first, array_iterator last)`
|
||||
class basic_json|remove(const std::string& name)|<em>✓</em>|`erase(const string_view_type& name)`
|
||||
class basic_json|parse_stream(std::istream& is)|<em>✓</em>|`parse(std::istream& is)`
|
||||
class basic_json|parse_stream(std::istream& is, parse_error_handler& err_handler)|<em>✓</em>|`parse(std::istream& is, parse_error_handler& err_handler)`
|
||||
class basic_json|as_int() const|<em>✓</em>|`as<int>`
|
||||
class basic_json|as_uint() const|<em>✓</em>|`as<unsigned int>`
|
||||
class basic_json|as_long() const|<em>✓</em>|`as<long>`
|
||||
class basic_json|as_ulong() const|<em>✓</em>|`as<unsigned long>`
|
||||
class basic_json|as_longlong() const|<em>✓</em>|`as<long long>`
|
||||
class basic_json|as_ulonglong() const|<em>✓</em>|`as<unsigned long long>`
|
||||
class basic_json|is_longlong() const|<em>✓</em>|is<long long>()
|
||||
class basic_json|is_ulonglong() const|<em>✓</em>|is<unsigned long long>()
|
||||
class basic_json|is_numeric() const|<em>✓</em>|`is_number()`
|
||||
class basic_json|remove_member(const std::string& name)|<em>✓</em>|erase(const string_view_type& name)
|
||||
class basic_json|const json& get(const std::string& name) const|<em>✓</em>|Use const json get(const std::string& name, T default_val) const with default `json::null_type()`
|
||||
class basic_json|has_member(const std::string& name) const|<em>✓</em>|Use `contains(const string_view_type& name)`
|
||||
class basic_json|has_key(const std::string& name) const|<em>✓</em>|Use `contains(const string_view_type& name)`
|
||||
class basic_json|add|<em>✓</em>|`push_back`
|
||||
class basic_json|set|<em>✓</em>|`insert_or_assign`
|
||||
class basic_json|members()|<em>✓</em>|object_range()
|
||||
class basic_json|elements()|<em>✓</em>|array_range()
|
||||
class basic_json|begin_members()|<em>✓</em>|Use object_range().begin()
|
||||
class basic_json|end_members()|<em>✓</em>|Use object_range().end()
|
||||
class basic_json|begin_elements()|<em>✓</em>|Use array_range().begin()
|
||||
class basic_json|end_elements()|<em>✓</em>|Use array_range().end()
|
||||
class basic_json|is_empty() const|<em>✓</em>|`empty()`
|
||||
class basic_json|parse_string(const std::string& s)|<em>✓</em>|parse(const std::string& s)
|
||||
class basic_json|parse_string(const std::string& s,parse_error_handler& err_handler)|<em>✓</em>|Use parse(const std::string& s,parse_error_handler& err_handler)
|
||||
class basic_json|resize_array(size_t n)|<em>✓</em>|resize(size_t n)
|
||||
class basic_json|resize_array(size_t n, const json& val)|<em>✓</em>|resize(size_t n, const json& val)
|
||||
class basic_json|to_stream|<em>✓</em>|Use dump
|
||||
class basic_json|write|<em>✓</em>|Use dump
|
||||
class basic_json|`json` initializer-list constructor||Construct from `json::array` with initializer-list
|
||||
class basic_json_deserializer|json_deserializer|<em>✓</em>|Use json_decoder<json>`
|
||||
class basic_json_deserializer|wjson_deserializer|<em>✓</em>|Use `json_decoder<wjson>`
|
||||
class basic_json_deserializer|ojson_deserializer|<em>✓</em>|Use `json_decoder<ojson>`
|
||||
class basic_json_deserializer|wojson_deserializer|<em>✓</em>|Use `json_decoder<wojson>`
|
||||
class basic_json|owjson|<em>✓</em>|wojson`
|
||||
class basic_json|member_type name()|<em>✓</em>|key()
|
||||
class basic_json|rename_name_filter|<em>✓</em>|rename_object_member_filter`
|
||||
class basic_json|any||removed
|
||||
class basic_json|member_type|<em>✓</em>|key_value_pair_type
|
||||
class basic_json|kvp_type|<em>✓</em>|key_value_pair_type
|
||||
class basic_json|null||Constant removed. Use static member function `json::null()`
|
||||
class basic_json|an_object||Constant removed. Use the default constructor `json()` instead.
|
||||
class basic_json|an_array||Constant removed. Use assignment to `json::array()` or `json::make_array()` instead.
|
||||
class json_decoder|root()|<em>✓</em>|get_result()
|
||||
class json_content_handler|begin_json|<em>✓</em>|Removed
|
||||
class json_content_handler|end_json|<em>✓</em>|`flush`
|
||||
class json_content_handler|begin_document|<em>✓</em>|Removed
|
||||
class json_content_handler|end_document|<em>✓</em>|`flush`
|
||||
class json_content_handler|do_begin_json||Remove
|
||||
class json_content_handler|do_end_json||Remove
|
||||
class json_content_handler|do_begin_document||Remove
|
||||
class json_content_handler|do_end_document||Remove
|
||||
class output_format|`output_format`|<em>✓</em>|`json_serializing_options`
|
||||
class serialization_options|`serialization_options`|<em>✓</em>|Use `json_serializing_options`
|
||||
class json_reader|max_depth(),max_depth(value)|<em>✓</em>|Use `json_serializing_options::max_nesting_depth`
|
||||
class json_reader|max_nesting_depth(),max_nesting_depth(value)|<em>✓</em>|Use `json_serializing_options::max_nesting_depth`
|
||||
class json_reader|json_input_handler& parent()|<em>✓</em>|Use json_input_handler& input_handler()
|
||||
json_input_handler class|do_longlong_value(long long value, const parsing_context& context)||Override do_integer_value(int64_t value, const parsing_context& context)
|
||||
class json_reader|do_ulonglong_value(unsigned long long value, const parsing_context& context)||Removed, override do_uinteger_value(uint64_t value, const parsing_context& context)
|
||||
class json_reader|do_double_value(double value, const basic_parsing_context<CharT>& context)||Removed, override do_double_value(double value, uint8_t precision, const basic_parsing_context<CharT>& context)
|
||||
class json_reader|`value(value,context)`| |Use `string_value(value,context)`, `integer_value(value,context)`, `uinteger_value(value,context)`, `double_value(value,precision,context)`, `bool_value(value,context)`, `null_value(context)`
|
||||
class json_output_handler class|do_longlong_value(long long value)||Removed, override do_integer_value(int64_t value)
|
||||
 |do_ulonglong_value(unsigned long long value)||Removed, override do_uinteger_value(uint64_t value)
|
||||
 |do_double_value(double value)||Removed, override do_double_value(double value, uint8_t precision)
|
||||
 |`value(value)`|<em>✓</em>|Use `string_value(value)`, `integer_value(value)`, `uinteger_value(value)`, `double_value(value,precision=0)`, `bool_value(value)`, `null_value(context)`
|
||||
basic_parsing_context|last_char()|<em>✓</em>|Use current_char()
|
||||
json_filter|parent()|<em>✓</em>|Use downstream_handler()
|
||||
 |input_handler()|<em>✓</em>|Use downstream_handler()
|
||||
file `csv_parameters.hpp`| ||Use `csv_options.hpp`
|
||||
file `csv_serializing_options.hpp`| ||Use `csv_serializing_options.hpp`
|
||||
class `csv_parameters`|`csv_parameters`| |Use `csv_serializing_options`
|
||||
class `csv_serializing_options`|`csv_parameters`| |Use `csv_options`
|
||||
class `csv_options`|`header(std::string value)`| |Use `column_names(const std::string& value)`
|
||||
class `csv_options`|`column_names(std::vector<std::string>> value)`|<em>✓</em>|Use `column_names(const std::string& value)`
|
||||
class `csv_options`|`data_types(std::string value)`||Use `column_types(const std::string& value)`
|
||||
class `csv_options`|`column_types(std::vector<std::string>> value)`|<em>✓</em>|Use `column_types(const std::string& value)`
|
||||
class `csv_options`|`column_defaults(std::vector<std::string>> value)`|<em>✓</em>|Use `column_defaults(const std::string& value)`
|
||||
file `output_format.hpp`| | |Use `json_serializing_options.hpp`
|
||||
file `json_serializing_options`.hpp| | |Use `json_options.hpp`
|
||||
class json_options|`array_array_block_option accessor and modifier` accessor and modifier| |Use `array_array_line_splits` accessor and modifier
|
||||
class json_options|`array_object_block_option accessor and modifier`| |Use `array_object_line_splits` accessor and modifier
|
||||
class json_options|`object_array_block_option accessor and modifier`| |Use `object_array_line_splits` accessor and modifier
|
||||
class json_options|`object_object_line_splits accessor and modifier`| |Use `object_object_line_splits` accessor and modifier
|
||||
class json_options|`array_array_line_splits accessor and modifier` accessor and modifier|<em>✓</em>|Use `array_array_line_splits` accessor and modifier
|
||||
class json_options|`array_object_line_splits accessor and modifier`|<em>✓</em>|Use `array_object_line_splits` accessor and modifier
|
||||
class json_options|`object_array_line_splits accessor and modifier`|<em>✓</em>|Use `object_array_line_splits` accessor and modifier
|
||||
class json_options|`object_object_line_splits accessor and modifier`|<em>✓</em>|Use `object_object_line_splits` accessor and modifier
|
||||
msgpack|`jsoncons_ext/msgpack/message_pack.hpp` header file|<em>✓</em>|Use `jsoncons_ext/msgpack/msgpack.hpp`
|
||||
 |`encode_message_pack`|<em>✓</em>|Use `encode_msgpack`
|
||||
 |`decode_message_pack`|<em>✓</em>|Use `decode_msgpack`
|
||||
|
Before Width: | Height: | Size: 4.0 KiB |
|
@ -1 +0,0 @@
|
|||
<mxfile modified="2019-02-06T01:49:37.530Z" host="www.draw.io" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.81 Safari/537.36" etag="qa66pJrbfM1znhkBI0u5" version="10.1.8" type="device"><diagram id="iK-0d-7Yl-5MlnfMu26I" name="Page-1">3VdNc9owEP01PtKxLaDkmABJW4ZMUzoDOTGKtbHVyhKVBZj++kq2jD8zIW2G6cAF7Vvtyvv0vCwOGsfpncSbaC4IMMd3SeqgieP7nut7+ssghxxBfT8HQkmJ3VQCC/obikiLbimBpLZRCcEU3dTBQHAOgaphWEqxr297Fqx+6gaH0AIWAWZtdEmJinJ0NHBL/BPQMCpO9lzriXGx2QJJhInYVyA0ddBYCqHyVZyOgRnyCl7yuNsXvMcHk8DVKQHT++8pnz0sIn/8a6aW8/gx/dKzWXaYbW3BTzihwfpHIvhac6p08nWEOWEgHX/I9Ek3T2YVmlUXkpWqDgV/Umw5AfMIrnbvI6pgscGB8e61YjQWqZhpyztGV0sqng+kgrQC2RLvQMSg5EFvsd6RZdvKzSvY35eX5w0tFlUurm8xbPUSHjOXlOqFZfUNDH9sMZxxSyDQ70onp//C4DNlbCyYkFksguyj8URJ8RMqHjREV4i8D+cnkT44J+mjFuktWoGTa9MftBUwnGjR15mElKqVJd2sH836w8Bak7TimhwKg+uHXxUJjFGJMmYZlllF3It3kIitDOB1dSksQ1Cvv+dAat2ufaOVG+u6sAKTwLCiu3qP7LpFe8JXQXVlR8H063rxUUMHedk2qNrSGnmuGrobNfLktLTyZJI6Fn2SysLdPPJn9yv8DcLe8mEGuxn0Bheoss5C0UWqp99INDyveoYXop5q7+ks9P/qPQO30TTcv5WP19Chd179tAeLzzwCSRXm+mXWEzfFocRxS1T6R13VZVQfDrjg0JgkLIQZDbnRopaAHl3QjRkRqJ6Vr60jpoSYYzqnlPoc8w5jh9do/77bMXagDiX5bx87tFlO6vkNlv930PQP</diagram></mxfile>
|
Before Width: | Height: | Size: 5.1 KiB |
|
@ -1 +0,0 @@
|
|||
<mxfile modified="2019-03-29T03:23:40.777Z" host="www.draw.io" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36" etag="rL7pmdpc4vrqfVVPYWcp" version="10.5.9" type="device"><diagram id="iK-0d-7Yl-5MlnfMu26I" name="Page-1">vVbBctowEP0aH9OxLSBwTAxNW4ZMUzoDOTGKtbHVyhKVBZh+fSUsY8t2GjLNNIeM9q12Jb19u8ZDUVbcSbxNF4IA80KfFB6aemF4HYz1fwMcS2DgT0ogkZSUUFADS/obLOhbdEcJ5M5GJQRTdOuCseAcYuVgWEpxcLc9C+aeusUJdIBljFkXXVGi0hIdD/0a/wQ0SauTA996MlxttkCeYiIODQjNPBRJIVS5yooImOGu4qWM+/iC93wxCVxdEjC7/17w+cMyDaNfc7VaZI/FlyubZY/Zzj74Cec03vzIBd9oTpVOvkkxJwykF46YPun2yawSs+pDTk9Vx4o/KXacgLmCr92HlCpYbnFsvActGI2lKmPaCs7RzSdV9wOpoGhA9ol3IDJQ8qi3WO/Ysm3lFlTsH+riBSOLpY3CDSyGrV6Sc+aaUr2wrL6B4eu/MQw81g3Ty+y/8PhMGYsEE/IUi+D0p/FcSfETGh40QhNE3of5i6gf/E/qxx3qO7QCJzdmSmgrZjjXhXGZhIKqtSXdrB/N+sPQWtOi4ZoeK4Pry6+rBMZoRBmzDjtZVdyLNcjFTsbwusYUlgmo17sdiDPzuhVtVGzYU7AKk8Cwont3UvZV0Z7wVVD9srNgBq5eQtTSQflsG9QcbK08k5buxq08JS2dPCdJnR99kcqS/SIN5/dr/A2Sq9XDHPZz6GnwzzwFSRXmumj6y0dxInHWkZ5uK+WKzW1PLji0etlCmNGEG8VqoejhgW5Nk1L9zbqxjowSYo7pnRPuJHmHxg9aBQj9nsZHPToK39742qy/mGUF658daPYH</diagram></mxfile>
|
Before Width: | Height: | Size: 4.1 KiB |
|
@ -1 +0,0 @@
|
|||
<mxfile modified="2019-02-06T01:55:13.660Z" host="www.draw.io" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.81 Safari/537.36" etag="4icZ4XetYWPc_3c4wqeo" version="10.1.8" type="device"><diagram id="iK-0d-7Yl-5MlnfMu26I" name="Page-1">3VdRb9owEP41PDIlMTD62ALrNkS1jknQJ+TG18SbYzPHQNivn00cEidpSydUTfCC77PvnPvuy3F00CjJbiVexzNBgHUCj2QdNO4Ege8Fvv4yyD5HUC/IgUhSYg+VwJz+gcLTohtKIHUOKiGYomsXDAXnECoHw1KKnXvsSTD31jWOoAHMQ8ya6IISFefosO+V+GegUVzc7Ht2J8HFYQukMSZiV4HQpINGUgiVr5JsBMyQV/CS+316Zvf4YBK4OsVhcvcj49P7eRyMfk/VYpY8ZF+7NsoWs41N+BGnNFz9TAVfaU6VDr6KMScMZCcYMH3TzaNZRWZlE1P7gi0pNpyAudDT27uYKpivcWh2d1ofGotVwrTlH72rCRRPA1JBVoFsQrcgElByr4/Y3aHl1orLL7jelaXyBxaLK2XqWQxbdUTHyCWBemE5fAOfH1/i84kydX4adVQ2EkzIgy+Cw0fjqZLiF1R20ABdIXIe4k9ivv+ezA8bzDdoBU6uTUvQVshwquviMgkZVUtLulk/mPWHvrXGWWVrvC8Mrh9+WQQwRsXLmKXbwSr8nq1BKjYyhNclprCMQL3+agNxGlyzopWKtRWswCQwrOjWbYttVbQ3fBNUZ3YUTM/VS4BqOsjTtk7VLlaLc1XT3bAWJ6elEecgqWPSJ6ks2s7iYHq3xN8h6i7up7CdQrd/gSprTRRdpHp6tUCD91XP4ELUU+09rYn+X72n79Wahvev8vFrOvTfVz/N6eILj0FShbl+mfWQTXEkcdIQlf5RV66M3OGACw61ScJCmNGIGy1qCejRBd2YEYHq8fjabiSUEHNN65TizjFnGDv8WvsPvJaxA7UoKXj72KHNcjjPK1j+xUGTvw==</diagram></mxfile>
|
Before Width: | Height: | Size: 6.1 KiB |
|
@ -1 +0,0 @@
|
|||
<mxfile modified="2019-03-28T18:41:55.313Z" host="www.draw.io" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36" etag="cKI-reTjnIO1Dr4pFHCv" version="10.5.9" type="device"><diagram id="aNkMF165W3cufMvMLNcI" name="Page-1">zVbJbtswEP0aHVtIVLxcGztNDm1R1ECbngRGHEtsKVKhqEjq15eMSK1OnAZG6osx82Yh+eZ5IC/cZPW1xHn6WRBgHvJJ7YVbD6EVCvSvAZoWuAj8FkgkJS0U9MCO/gELurSSEihGiUoIpmg+BmPBOcRqhGEpRTVO2ws2PjXHCcyAXYzZHP1BiUpbdL3we/wGaJK6kwPfRjLski1QpJiIagCFV164kUKo1srqDTDDneOlrfv4RLS7mASuXlKw/97sv+W/b+7Fl+h+HW0vy0/NO9vlAbPSPvgOFzSOfhWCRwRiPc5I5IoKXthXqMZRI0XJCZjuvhdeVilVsMtxbKKV1oLGUpUx7QXanN/WHQ1SQT2A7O2vQWSgZKNTbPTCEmmVtLZu1Y8lWFosHYzElWGrhKRr3JOlDcvXP3CHnuMO+Dlz1xH138gLnyPvXFhDywlt6ABt6C1pW85om5EEnHwwi097McOFJnXMC9RU3VoKjf3T2O8X1tvWg9C2cQ7Xl791DYwzqDJuX/boubonZ1CIUsZwXB8KywTU8T8hkNEan090MLHFgYE5TALDij6Ml/+hKdoTvgqqX9YJphNDMxGQa9G+21YNl/W00WrSKJg0aomZNXoUVffs1+tsdQKdnVozR7UQnJUWZstjuhReqoX1RAroVFLQbv/50ab333Dh1V8=</diagram></mxfile>
|
Before Width: | Height: | Size: 5.6 KiB |
|
@ -1 +0,0 @@
|
|||
<mxfile modified="2019-02-07T09:01:31.607Z" host="www.draw.io" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.81 Safari/537.36" etag="zrG5kpKxJ_ZdgWPk9VR7" version="10.1.8" type="device"><diagram id="iK-0d-7Yl-5MlnfMu26I" name="Page-1">5VddU9swEPw1eaTjWEkIjxAopRloaZgB+pJR7MMWlaVUVhKHX88plvxNoQwtnSkvSCudZO3trZQemSTZqaLL+FyGwHu+F2Y9ctzz/b7nj/CfQbY5QgaDHIgUC+2kEpixB3CRFl2xENLaRC0l12xZBwMpBAS6hlGl5KY+7U7y+q5LGkELmAWUt9FrFuo4R8dDr8Q/AYtit3PfsyMJdZMtkMY0lJsKRE56ZKKk1HkrySbADXmOlzzu4xOjxYcpEPolAScXV5mYXs5if/Jzqq/Pk9vs855dZU35yh54QVMWzO9TKeZ3jGtQPX/EcYOjhWlFpmXPo7eOJCVXIgSzj4fDm5hpmC1pYEY3KAvEYp1w7PWL6Op3u48ApSGrQPYcpyAT0GqLU+yoP7acWlH1HcebMkUFFlfSM7AYtaqIiqVL4rBhufsNHvef4BEPSROYy8U9inOeQLIA9Yd4xVX5RHKpdrEEdn+Ip1rJH1AZISNyQMK3ycRg8HwmfO9vZmLcykSLVhDhobEG7AWcppinOpOQMX1jSTftW9P+MLS946wydLx1HYEff+MWMJ1KlOmWYbuei3syB6lcqQCel5ymKgL9fIlDWDO6dkYrGRt2JMxhCjjVbF23x64s2h2+SoYnK0vXqwvGJw0h5Oe2UVU7ay40bChv3FgoJ6a10E5UxbFfpLNofR7704sb+g2ivevLKayn0FHxZyIGxTQVmDa88BiNFE1a4sPC0nW51QtUSAGNarYQ5SwSRrMoFbQPcmTKlOFVdWgHEhaGZptOp6h7yVuY8P6wnkmvw4RJh5L8Nyj90e2Xq71+P/2+PfQeSHa23h/FHZeZ89h0SYVz2coFh48GjQTMYyqQuMKRcfNqwLtfd+/psZ1E+/+Lx7oXZ8Vjf6W8f8RjG68j/+CVFltUr1uoKahXWyx2y4dvPr38+UBOHgE=</diagram></mxfile>
|
Before Width: | Height: | Size: 9.5 KiB |
|
@ -1 +0,0 @@
|
|||
<mxfile modified="2019-03-21T15:04:20.252Z" host="www.draw.io" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36" etag="TLDZl63TdUk_PH3vDP6i" version="10.5.2" type="device"><diagram id="iK-0d-7Yl-5MlnfMu26I" name="Page-1">7Vhdb9owFP01PHYKcWjhsQXabajVOia1faqs+Dbx5tjMMRD262cT59NAWwkVtIEQso/ta/vcc+8l6aBhkt1IPItvBQHW8T2SddCo4/uDwUD/GmCVA4FngUhSkkPdCpjSP2BBz6JzSiBtTFRCMEVnTTAUnEOoGhiWUiyb014Ea+46wxE4wDTEzEUfKFFxjvZ7XoV/BhrFxc5dz44kuJhsgTTGRCxrEBp30FAKofJWkg2BGe4KXvJ111tGy4NJ4OotC8Z3PzI+uZ/G/vD3RD3cJk/Z1zNrZYHZ3F44VXr+pf5CFsJMUcHt8dWq4ESKOSdgzHoddLWMqYLpDIdmdKlFoLFYJUz3urrpHrPYE6SCrAbZY9+ASEDJlZ5iR88tg1ZC3YLRZeWQkva45ozAYthqICotVzTphmXqHaxdbGdNzrmiCTyD1p48OHO+d2zU9R3qHJKAk0sTuboXMpymNGzyAhlVj5ZC034y7U892xtltaHRquhwffjHwoDp1FaZbrVs3SvWbfVBKuYyhNc1orCMQL0egUAaecj1aM1jvQ0OKzAJDCu6aGavTV60O3wTVN+sFEzQ1IuPWjrIr20X1ZNNy86gpbt+y05Oi2NnLany0m9SWbS4jf3J3SP+DtHZw/0EFhPYldbSVaogOZL4RMEB43Mjc/4/GJ+7JPJqfF6c4nP/8Ync+AS5j5h8oYwNBdNmzFoE64/GUyXFL6iNoHM0QGQ/UdxrVdm+G8SDj4zhwGH3Zyr48/H8oWunveDQWa/3v2Q95Ga9XRI6Zb19Zr3zk8o21uAjURlqPWeWz53vlVnQbRnqfqzO3MfTLzwGSRXm2m2+RyiOJE4c8ensrZpya5ZNLji0aqyFMKMRN5rVUgGNX5laQEPMLu1AQgkx22wsLs3ys4f60n5jUDqgXmDQBiX57y8wulu9w8k9WL0IQ+O/</diagram></mxfile>
|
|
@ -1,200 +0,0 @@
|
|||
### jsoncons::encode_json
|
||||
|
||||
Encode a C++ data structure to a JSON formatted string or stream. `encode_json` will work for all types that
|
||||
have [json_type_traits](https://github.com/danielaparker/jsoncons/blob/master/doc/ref/json_type_traits.md) defined.
|
||||
|
||||
#### Header
|
||||
```c++
|
||||
#include <jsoncons/json.hpp>
|
||||
|
||||
template <class T, class CharT>
|
||||
void encode_json(const T& val,
|
||||
std::basic_ostream<CharT>& os,
|
||||
const basic_json_encode_options<CharT>& options = basic_json_options<CharT>::default_options(),
|
||||
indenting line_indent = indenting::no_indent); // (1)
|
||||
|
||||
template <class T, class CharT>
|
||||
void encode_json(const T& val,
|
||||
std::basic_ostream<CharT>& os,
|
||||
indenting line_indent); // (2)
|
||||
|
||||
template <class T, class CharT>
|
||||
void encode_json(const T& val,
|
||||
std::basic_string<CharT>& s,
|
||||
const basic_json_encode_options<CharT>& options = basic_json_options<CharT>::default_options(),
|
||||
indenting line_indent = indenting::no_indent); // (3)
|
||||
|
||||
template <class T, class CharT>
|
||||
void encode_json(const T& val,
|
||||
std::basic_string<CharT>& s,
|
||||
indenting line_indent); // (4)
|
||||
|
||||
template <class T, class CharT>
|
||||
void encode_json(const T& val,
|
||||
basic_json_content_handler<CharT>& receiver); // (5)
|
||||
|
||||
template <class T, class CharT, class ImplementationPolicy, class Allocator>
|
||||
void encode_json(const basic_json<CharT,ImplementationPolicy,Allocator>& j,
|
||||
const T& val,
|
||||
std::basic_ostream<CharT>& os,
|
||||
const basic_json_encode_options<CharT>& options = basic_json_options<CharT>::default_options(),
|
||||
indenting line_indent = indenting::no_indent); // (6)
|
||||
|
||||
template <class T, class CharT, class ImplementationPolicy, class Allocator>
|
||||
void encode_json(const basic_json<CharT,ImplementationPolicy,Allocator>& j,
|
||||
const T& val,
|
||||
std::basic_ostream<CharT>& os,
|
||||
indenting line_indent); // (7)
|
||||
|
||||
template <class T, class CharT, class ImplementationPolicy, class Allocator>
|
||||
void encode_json(const basic_json<CharT,ImplementationPolicy,Allocator>& j,
|
||||
const T& val,
|
||||
std::basic_string<CharT>& s,
|
||||
const basic_json_encode_options<CharT>& options = basic_json_options<CharT>::default_options(),
|
||||
indenting line_indent = indenting::no_indent); // (8)
|
||||
|
||||
template <class T, class CharT, class ImplementationPolicy, class Allocator>
|
||||
void encode_json(const basic_json<CharT,ImplementationPolicy,Allocator>& j,
|
||||
const T& val,
|
||||
std::basic_string<CharT>& s,
|
||||
indenting line_indent); // (9)
|
||||
|
||||
template <class T, class CharT, class ImplementationPolicy, class Allocator>
|
||||
void encode_json(const basic_json<CharT, ImplementationPolicy, Allocator>& j,
|
||||
const T& val,
|
||||
basic_json_content_handler<CharT>& receiver); // (10)
|
||||
```
|
||||
|
||||
(1) Encode `val` to output stream with the specified options and line indenting.
|
||||
|
||||
(2) Encode `val` to output stream with the specified line indenting.
|
||||
|
||||
(3) Encode `val` to string with the specified options and line indenting.
|
||||
|
||||
(4) Encode `val` to string with the specified line indenting.
|
||||
|
||||
(5) Convert `val` to json events and stream through content handler.
|
||||
|
||||
Functions (1)-(5) perform encodings using the default json type `basic_json<CharT>`.
|
||||
Functions (6)-(10) are the same but perform encodings using the supplied `basic_json`.
|
||||
|
||||
#### Parameters
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>val</td>
|
||||
<td>C++ data structure</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>handler</td>
|
||||
<td>JSON output handler</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>options</td>
|
||||
<td>Serialization options</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>os</td>
|
||||
<td>Output stream</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>indenting</td>
|
||||
<td><code>indenting::indent</code> to pretty print, <code>indenting::no_indent</code> for compact output</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
#### Return value
|
||||
|
||||
None
|
||||
|
||||
#### See also
|
||||
|
||||
- [json_content_handler](json_content_handler.md)
|
||||
- [json_options](json_options.md)
|
||||
|
||||
### Examples
|
||||
|
||||
#### Map with string-tuple pairs
|
||||
|
||||
```c++
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <tuple>
|
||||
#include <jsoncons/json.hpp>
|
||||
|
||||
using namespace jsoncons;
|
||||
|
||||
int main()
|
||||
{
|
||||
typedef std::map<std::string,std::tuple<std::string,std::string,double>> employee_collection;
|
||||
|
||||
employee_collection employees =
|
||||
{
|
||||
{"John Smith",{"Hourly","Software Engineer",10000}},
|
||||
{"Jane Doe",{"Commission","Sales",20000}}
|
||||
};
|
||||
|
||||
std::cout << "(1)\n" << std::endl;
|
||||
encode_json(employees,std::cout);
|
||||
std::cout << "\n\n";
|
||||
|
||||
std::cout << "(2) Again, with pretty print\n" << std::endl;
|
||||
encode_json(employees, std::cout, jsoncons::indenting::indent);
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```
|
||||
(1)
|
||||
|
||||
{"Jane Doe":["Commission","Sales",20000.0],"John Smith":["Hourly","Software Engineer",10000.0]}
|
||||
|
||||
(2) Again, with pretty print
|
||||
|
||||
{
|
||||
"Jane Doe": ["Commission","Sales",20000.0],
|
||||
"John Smith": ["Hourly","Software Engineer",10000.0]
|
||||
}
|
||||
```
|
||||
|
||||
#### Contain JSON output in an object
|
||||
|
||||
```c++
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <tuple>
|
||||
#include <jsoncons/json.hpp>
|
||||
|
||||
using namespace jsoncons;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::map<std::string,std::tuple<std::string,std::string,double>> employees =
|
||||
{
|
||||
{"John Smith",{"Hourly","Software Engineer",10000}},
|
||||
{"Jane Doe",{"Commission","Sales",20000}}
|
||||
};
|
||||
|
||||
json_encoder encoder(std::cout, jsoncons::indenting::indent);
|
||||
|
||||
encoder.begin_object();
|
||||
encoder.write_name("Employees");
|
||||
encode_json(employees, encoder);
|
||||
encoder.end_object();
|
||||
encoder.flush();
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```json
|
||||
{
|
||||
"Employees": {
|
||||
"Jane Doe": ["Commission","Sales",20000.0],
|
||||
"John Smith": ["Hourly","Software Engineer",10000.0]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### See also
|
||||
|
||||
- [decode_json](decode_json.md)
|
||||
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
### jsoncons::indenting
|
||||
|
||||
```c++
|
||||
enum class indenting {no_indent, indent}
|
||||
```
|
||||
|
||||
#### Header
|
||||
```c++
|
||||
#include <jsoncons/json_options.hpp>
|
||||
```
|
||||
|
||||
Specifies indentation options for the [json_encoder](json_encoder.md)
|
||||
|
|
@ -1,397 +0,0 @@
|
|||
### jsoncons::json
|
||||
|
||||
```c++
|
||||
typedef basic_json<char,
|
||||
ImplementationPolicy = sorted_policy,
|
||||
Allocator = std::allocator<char>> json
|
||||
```
|
||||
The class `json` is an instantiation of the `basic_json` class template that uses `char` as the character type. The order of an object's name/value pairs is not preserved, they are sorted alphabetically by name. If you want to preserve the original insertion order, use [ojson](ojson.md) instead.
|
||||
|
||||
The class `json` resembles a union. An instance of `json` holds a data item of one of its alternative types:
|
||||
|
||||
- null
|
||||
- bool
|
||||
- int64
|
||||
- uint64
|
||||
- double
|
||||
- string
|
||||
- byte string
|
||||
- array
|
||||
- object
|
||||
|
||||
The data item may be tagged with a [semantic_tag](semantic_tag.md) that provides additional
|
||||
information about the data item.
|
||||
|
||||
When assigned a new value, the old value is overwritten. The type of the new value may be different from the old value.
|
||||
|
||||
The `jsoncons` library will rebind the supplied allocator from the template parameter to internal data structures.
|
||||
|
||||
#### Header
|
||||
```c++
|
||||
#include <jsoncons/json.hpp>
|
||||
```
|
||||
|
||||
#### Member types
|
||||
|
||||
Member type |Definition
|
||||
------------------------------------|------------------------------
|
||||
`json_type`|json
|
||||
`reference`|json&
|
||||
`const_reference`|const json&
|
||||
`pointer`|json*
|
||||
`const_pointer`|const json*
|
||||
`allocator_type`|Allocator type
|
||||
`char_allocator`|String allocator type
|
||||
`array_allocator`|Array allocator type
|
||||
`object_allocator`|Object allocator
|
||||
`string_view_type`|A non-owning view of a string, holds a pointer to character data and length. Supports conversion to and from strings. Will be typedefed to the C++ 17 [string view](http://en.cppreference.com/w/cpp/string/basic_string_view) if `JSONCONS_HAS_STRING_VIEW` is defined in `jsoncons_config.hpp`, otherwise proxied.
|
||||
`key_value_type`|[key_value_type](json/key_value.md) is a class that stores a name and a json value
|
||||
`object`|json object type
|
||||
`array`|json array type
|
||||
`object_iterator`|A [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator) to [key_value_type](json/key_value.md)
|
||||
`const_object_iterator`|A const [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator) to const [key_value_type](json/key_value.md)
|
||||
`array_iterator`|A [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator) to `json`
|
||||
`const_array_iterator`|A const [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator) to `const json`
|
||||
|
||||
### Static member functions
|
||||
|
||||
<table border="0">
|
||||
<tr>
|
||||
<td><a href="json/parse.md">parse</a></td>
|
||||
<td>Parses JSON.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="json/make_array.md">make_array</a></td>
|
||||
<td>Makes a multidimensional json array.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a>const json& null()</a></td>
|
||||
<td>Returns a null value</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
### Member functions
|
||||
<table border="0">
|
||||
<tr>
|
||||
<td><a href="json/constructor.md">(constructor)</a></td>
|
||||
<td>constructs the json value</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="json/destructor.md">(destructor)</a></td>
|
||||
<td>destructs the json value</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="json/operator=.md">operator=</a></td>
|
||||
<td>assigns values</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
allocator_type get_allocator() const
|
||||
Returns the allocator associated with the json value.
|
||||
|
||||
#### Ranges and Iterators
|
||||
|
||||
<table border="0">
|
||||
<tr>
|
||||
<td><a href="json/array_range.md">array_range</a></td>
|
||||
<td>Returns a "range" that supports a range-based for loop over the elements of a `json` array.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="json/object_range.md">obect_range</a></td>
|
||||
<td>Returns a "range" that supports a range-based for loop over the key-value pairs of a `json` object.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
#### Capacity
|
||||
|
||||
<table border="0">
|
||||
<tr>
|
||||
<td><a>size_t size() const noexcept</a></td>
|
||||
<td>Returns the number of elements in a json array, or the number of members in a json object, or `zero`</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a>bool empty() const noexcept</a></td>
|
||||
<td>Returns <code>true</code> if a json string, object or array has no elements, otherwise <code>false</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a>size_t capacity() const</a></td>
|
||||
<td>Returns the size of the storage space currently allocated for a json object or array</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a>void reserve(size_t n)</a></td>
|
||||
<td>Increases the capacity of a json object or array to allow at least `n` members or elements</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a>void resize(size_t n)</a></td>
|
||||
<td>Resizes a json array so that it contains `n` elements</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a>void resize(size_t n, const json& val)</a></td>
|
||||
<td>Resizes a json array so that it contains `n` elements that are initialized to `val`</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a>void shrink_to_fit()</a></td>
|
||||
<td>Requests the removal of unused capacity</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
#### Accessors
|
||||
|
||||
<table border="0">
|
||||
<tr>
|
||||
<td><code>bool contains(const string_view_type& key) const</code></td>
|
||||
<td>Returns <code>true</code> if an object has a member with the given `key`, otherwise <code>false</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>bool count(const string_view_type& key) const</code></td>
|
||||
<td>Returns the number of object members that match `key`</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="json/is.md">is</a></td>
|
||||
<td>Checks if a json value matches a type.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="json/as.md">as</a></td>
|
||||
<td>Attempts to convert a json value to a value of a type.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
semantic_tag get_semantic_tag() const
|
||||
Returns the [semantic_tag](semantic_tag.md) associated with this value
|
||||
|
||||
json& operator[](size_t i)
|
||||
const json& operator[](size_t i) const
|
||||
Returns a reference to the value at position i in a json object or array.
|
||||
Throws `std::runtime_error` if not an object or array.
|
||||
|
||||
json& operator[](const string_view_type& name)
|
||||
Returns a proxy to a keyed value. If written to, inserts or updates with the new value. If read, evaluates to a reference to the keyed value, if it exists, otherwise throws.
|
||||
Throws `std::runtime_error` if not an object.
|
||||
If read, throws `std::out_of_range` if the object does not have a member with the specified name.
|
||||
|
||||
const json& operator[](const string_view_type& name) const
|
||||
If `name` matches the name of a member in the json object, returns a reference to the json object, otherwise throws.
|
||||
Throws `std::runtime_error` if not an object.
|
||||
Throws `std::out_of_range` if the object does not have a member with the specified name.
|
||||
|
||||
object_iterator find(const string_view_type& name)
|
||||
const_object_iterator find(const string_view_type& name) const
|
||||
Returns an object iterator to a member whose name compares equal to `name`. If there is no such member, returns `end_member()`.
|
||||
Throws `std::runtime_error` if not an object.
|
||||
|
||||
json& at(const string_view_type& name)
|
||||
const json& at(const string_view_type& name) const
|
||||
Returns a reference to the value with the specifed name in a json object.
|
||||
Throws `std::runtime_error` if not an object.
|
||||
Throws `std::out_of_range` if the object does not have a member with the specified name.
|
||||
|
||||
json& at(size_t i)
|
||||
const json& at(size_t i) const
|
||||
Returns a reference to the element at index `i` in a json array.
|
||||
Throws `std::runtime_error` if not an array.
|
||||
Throws `std::out_of_range` if the index is outside the bounds of the array.
|
||||
|
||||
template <class T>
|
||||
T get_with_default(const string_view_type& name,
|
||||
const T& default_val) const
|
||||
If `name` matches the name of a member in the json object, returns the member value converted to the default's data type, otherwise returns `default_val`.
|
||||
Throws `std::runtime_error` if not an object.
|
||||
|
||||
template <class T = std::string>
|
||||
T get_with_default(const string_view_type& name,
|
||||
const char_type* default_val) const
|
||||
Make `get_with_default` do the right thing for string literals.
|
||||
Throws `std::runtime_error` if not an object.
|
||||
|
||||
#### Modifiers
|
||||
|
||||
<table border="0">
|
||||
<tr>
|
||||
<td><a>void clear()</a></td>
|
||||
<td>Remove all elements from an array or members from an object, otherwise do nothing</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="json/erase.md">erase</a></td>
|
||||
<td>Erases array elements and object members</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="json/push_back.md">push_back</a></td>
|
||||
<td>Adds a value to the end of a json array</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="json/insert.md">insert</a></td>
|
||||
<td>Inserts elements</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="json/emplace_back.md">emplace_back</a></td>
|
||||
<td>Constructs a value in place at the end of a json array</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="json/emplace.md">emplace</a></td>
|
||||
<td>Constructs a value in place before a specified position in a json array</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="json/try_emplace.md">try_emplace</a></td>
|
||||
<td>Constructs a key-value pair in place in a json object if the key does not exist, does nothing if the key exists</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="json/insert_or_assign.md">insert_or_assign</a></td>
|
||||
<td>Inserts a key-value pair in a json object if the key does not exist, or assigns a new value if the key already exists</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="json/merge.md">merge</a></td>
|
||||
<td>Inserts another json object's key-value pairs into a json object, if they don't already exist.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="json/merge_or_update.md">merge_or_update</a></td>
|
||||
<td>Inserts another json object's key-value pairs into a json object, or assigns them if they already exist.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a>void swap(json& val)</a></td>
|
||||
<td>Exchanges the content of the <code>json</code> value with the content of <code>val</code>, which is another <code>json</code> value</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
#### Serialization
|
||||
|
||||
<table border="0">
|
||||
<tr>
|
||||
<td><a href="json/dump.md"</a>dump</td>
|
||||
<td>Serializes json value to a string, stream, or output handler.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
#### Non member functions
|
||||
|
||||
<table border="0">
|
||||
<tr>
|
||||
<td><code>bool operator==(const json& lhs, const json& rhs)</code></td>
|
||||
<td>Returns <code>true</true> if two json objects compare equal, <code>false</true> otherwise.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>bool operator!=(const json& lhs, const json& rhs)</code></td>
|
||||
<td>Returns <code>true</true> if two json objects do not compare equal, <code>false</true> otherwise.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>bool operator<(const json& lhs, const json& rhs)</code></td>
|
||||
<td>Compares the contents of lhs and rhs lexicographically.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>bool operator<=(const json& lhs, const json& rhs)</code></td>
|
||||
<td>Compares the contents of lhs and rhs lexicographically.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>bool operator>(const json& lhs, const json& rhs)</code></td>
|
||||
<td>Compares the contents of lhs and rhs lexicographically.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>bool operator>=(const json& lhs, const json& rhs)</code></td>
|
||||
<td>Compares the contents of lhs and rhs lexicographically.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
std::istream& operator>> (std::istream& os, json& val)
|
||||
Reads a `json` value from a stream.
|
||||
|
||||
std::ostream& operator<< (std::ostream& os, const json& val)
|
||||
Inserts json value into stream.
|
||||
|
||||
std::ostream& print(const json& val)
|
||||
std::ostream& print(const json& val, const json_options<CharT>& options)
|
||||
Inserts json value into stream using the specified [json_options](json_options.md) if supplied.
|
||||
|
||||
std::ostream& pretty_print(const json& val)
|
||||
std::ostream& pretty_print(const json& val, const json_options<CharT>& options)
|
||||
Inserts json value into stream using the specified [json_options](json_options.md) if supplied.
|
||||
|
||||
void swap(json& a, json& b)
|
||||
Exchanges the values of `a` and `b`
|
||||
|
||||
#### Deprecated names
|
||||
|
||||
As the `jsoncons` library has evolved, names have sometimes changed. To ease transition, jsoncons deprecates the old names but continues to support many of them. See the [deprecated list](deprecated.md) for the status of old names. The deprecated names can be suppressed by defining macro JSONCONS_NO_DEPRECATED, which is recommended for new code.
|
||||
|
||||
#### See also
|
||||
|
||||
- [ojson](ojson.md) constructs a json value that preserves the original name-value insertion order
|
||||
|
||||
- [wjson](wjson.md) constructs a wide character json value that sorts name-value members alphabetically
|
||||
|
||||
- [wojson](wojson.md) constructs a wide character json value that preserves the original name-value insertion order
|
||||
|
||||
### Examples
|
||||
|
||||
#### Accessors and defaults
|
||||
```c++
|
||||
json val;
|
||||
|
||||
val["field1"] = 1;
|
||||
val["field3"] = "Toronto";
|
||||
|
||||
double x1 = obj.contains("field1") ? val["field1"].as<double>() : 10.0;
|
||||
double x2 = obj.contains("field2") ? val["field2"].as<double>() : 20.0;
|
||||
|
||||
std::string x3 = obj.get_with_default("field3","Montreal");
|
||||
std::string x4 = obj.get_with_default("field4","San Francisco");
|
||||
|
||||
std::cout << "x1=" << x1 << '\n';
|
||||
std::cout << "x2=" << x2 << '\n';
|
||||
std::cout << "x3=" << x3 << '\n';
|
||||
std::cout << "x4=" << x4 << '\n';
|
||||
```
|
||||
Output:
|
||||
```c++
|
||||
x1=1
|
||||
x2=20
|
||||
x3=Toronto
|
||||
x4=San Francisco
|
||||
```
|
||||
#### Nulls
|
||||
```c++
|
||||
json obj;
|
||||
obj["field1"] = json::null();
|
||||
std::cout << obj << std::endl;
|
||||
```
|
||||
Output:
|
||||
```json
|
||||
{"field1":null}
|
||||
```
|
||||
#### Constructing json structures
|
||||
```c++
|
||||
json root;
|
||||
|
||||
root["persons"] = json::array();
|
||||
|
||||
json person;
|
||||
person["first_name"] = "John";
|
||||
person["last_name"] = "Smith";
|
||||
person["birth_date"] = "1972-01-30";
|
||||
|
||||
json address;
|
||||
address["city"] = "Toronto";
|
||||
address["country"] = "Canada";
|
||||
|
||||
person["address"] = std::move(address);
|
||||
|
||||
root["persons"].push_back(std::move(person));
|
||||
|
||||
std::cout << pretty_print(root) << std::endl;
|
||||
```
|
||||
Output:
|
||||
```c++
|
||||
{
|
||||
"persons":
|
||||
[
|
||||
{
|
||||
"address":
|
||||
{
|
||||
"city":"Toronto",
|
||||
"country":"Canada"
|
||||
},
|
||||
"birth_date":"1972-01-30",
|
||||
"first_name":"John",
|
||||
"last_name":"Smith"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
|
@ -1,45 +0,0 @@
|
|||
### jsoncons::json::array_range
|
||||
|
||||
```c++
|
||||
range<array_iterator> array_range();
|
||||
range<const_array_iterator> array_range() const;
|
||||
```
|
||||
Returns a "range" that supports a range-based for loop over the elements of a `json` array
|
||||
Throws `std::runtime_error` if not an array.
|
||||
|
||||
### Examples
|
||||
|
||||
#### Range-based for loop
|
||||
|
||||
```c++
|
||||
json j = json::array{"Toronto", "Vancouver", "Montreal"};
|
||||
|
||||
for (const auto& val : j.array_range())
|
||||
{
|
||||
std::cout << val.as<std::string>() << std::endl;
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```json
|
||||
Toronto
|
||||
Vancouver
|
||||
Montreal
|
||||
```
|
||||
|
||||
#### Array iterator
|
||||
```c++
|
||||
json j = json::array{"Toronto", "Vancouver", "Montreal"};
|
||||
|
||||
for (auto it = j.array_range().begin(); it != j.array_range().end(); ++it)
|
||||
{
|
||||
std::cout << it->as<std::string>() << std::endl;
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```json
|
||||
Toronto
|
||||
Vancouver
|
||||
Montreal
|
||||
```
|
||||
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
### jsoncons::json::as
|
||||
|
||||
```c++
|
||||
template <class T, class... Args>
|
||||
T as(Args&&... args) const; // (1)
|
||||
|
||||
bool as_bool() const; // (2)
|
||||
|
||||
template <class T>
|
||||
T as_integer() const; // (3)
|
||||
|
||||
double as_double() const; // (4)
|
||||
|
||||
string_view_type as_string_view() const; // (5)
|
||||
|
||||
std::string as_string() const; // (6)
|
||||
|
||||
byte_string as_byte_string() const; // (7)
|
||||
|
||||
bignum as_bignum() const; // (8)
|
||||
```
|
||||
|
||||
(1) Generic get `as` type `T`. Attempts to convert the json value to the template value type using [json_type_traits](../json_type_traits.md).
|
||||
|
||||
std::string as<std::string>() const noexcept
|
||||
std::string as<std::string>(const char_allocator& allocator) const noexcept
|
||||
If value is string, returns value, otherwise returns result of [dump](dump.md).
|
||||
|
||||
as<X<T>>()
|
||||
If the type `X` is not `std::basic_string` but otherwise satisfies [SequenceContainer](http://en.cppreference.com/w/cpp/concept/SequenceContainer), `as<X<T>>()` returns the `json` value as an `X<T>` if the `json` value is an array and each element is convertible to type `T`, otherwise throws.
|
||||
|
||||
as<X<std::string,T>>()
|
||||
If the type 'X' satisfies [AssociativeContainer](http://en.cppreference.com/w/cpp/concept/AssociativeContainer) or [UnorderedAssociativeContainer](http://en.cppreference.com/w/cpp/concept/UnorderedAssociativeContainer), `as<X<std::string,T>>()` returns the `json` value as an `X<std::string,T>` if the `json` value is an object and if each member value is convertible to type `T`, otherwise throws.
|
||||
|
||||
(2) Same as `as<bool>()`.
|
||||
Returns `true` if value is `bool` and `true`, or if value is integral and non-zero, or if value is floating point and non-zero, or if value is string and parsed value evaluates as `true`.
|
||||
Returns `false` if value is `bool` and `false`, or if value is integral and zero, or if value is floating point and zero, or if value is string and parsed value evaluates as `false`.
|
||||
Otherwise throws `std::runtime_exception`
|
||||
|
||||
(3) Same as `as<T>()` for integral type T.
|
||||
Returns integer value if value is integral, performs cast if value has double type, returns 1 or 0 if value has bool type, attempts conversion if value is string, otherwise throws.
|
||||
|
||||
(4) Same as `as<double>()`.
|
||||
Returns value cast to double if value is integral, returns `NaN` if value is `null`, attempts conversion if value is string, otherwise throws.
|
||||
|
||||
### Examples
|
||||
|
||||
#### Accessing integral, floating point, and boolean values
|
||||
|
||||
```c++
|
||||
json j = json::parse(R"(
|
||||
{
|
||||
"k1" : 2147483647,
|
||||
"k2" : 2147483648,
|
||||
"k3" : -10,
|
||||
"k4" : 10.5,
|
||||
"k5" : true,
|
||||
"k6" : "10.5"
|
||||
}
|
||||
)");
|
||||
|
||||
std::cout << "(1) " << j["k1"].as<int32_t>() << '\n';
|
||||
std::cout << "(2) " << j["k2"].as<int32_t>() << '\n';
|
||||
std::cout << "(3) " << j["k2"].as<long long>() << '\n';
|
||||
std::cout << "(4) " << j["k3"].as<signed char>() << '\n';
|
||||
std::cout << "(5) " << j["k3"].as<uint32_t>() << '\n';
|
||||
std::cout << "(6) " << j["k4"].as<int32_t>() << '\n';
|
||||
std::cout << "(7) " << j["k4"].as<double>() << '\n';
|
||||
std::cout << std::boolalpha << "(8) " << j["k5"].as<int>() << '\n';
|
||||
std::cout << std::boolalpha << "(9) " << j["k5"].as<bool>() << '\n';
|
||||
std::cout << "(10) " << j["k6"].as<double>() << '\n';
|
||||
|
||||
```
|
||||
Output:
|
||||
```
|
||||
|
||||
(1) 2147483647
|
||||
(2) -2147483648
|
||||
(3) 2147483648
|
||||
(4) ÷
|
||||
(5) 4294967286
|
||||
(6) 10
|
||||
(7) 10.5
|
||||
(8) 1
|
||||
(9) true
|
||||
(10) 10.5
|
||||
```
|
||||
|
||||
#### Accessing a `json` array value as a `std::vector`
|
||||
```c++
|
||||
std::string s = "{\"my-array\" : [1,2,3,4]}";
|
||||
json val = json::parse(s);
|
||||
std::vector<int> v = val["my-array"].as<std::vector<int>>();
|
||||
for (size_t i = 0; i < v.size(); ++i)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
std::cout << ",";
|
||||
}
|
||||
std::cout << v[i];
|
||||
}
|
||||
std::cout << std::endl;
|
||||
```
|
||||
Output:
|
||||
```
|
||||
1,2,3,4
|
||||
```
|
||||
|
||||
#### Accessing a `json` byte string as a [byte_string](../byte_string.md)
|
||||
```c++
|
||||
json j(byte_string("Hello"));
|
||||
byte_string bs = j.as<byte_string>();
|
||||
|
||||
std::cout << bs << std::endl;
|
||||
```
|
||||
Output:
|
||||
```
|
||||
0x480x650x6c0x6c0x6f
|
||||
```
|
||||
|
|
@ -1,150 +0,0 @@
|
|||
### `jsoncons::json::json`
|
||||
|
||||
```c++
|
||||
json(); // (1)
|
||||
|
||||
json(const allocator_type& allocator); // (2)
|
||||
|
||||
json(std::initializer_list<json> list, const allocator_type& allocator); // (3)
|
||||
|
||||
json(const json& val); // (4)
|
||||
|
||||
json(const json& val, const allocator_type& allocator); // (5)
|
||||
|
||||
json(json&& val) noexcept; // (6)
|
||||
|
||||
json(json&& val, const allocator_type& allocator) noexcept; // (7)
|
||||
|
||||
json(const array& val); // (8)
|
||||
|
||||
json(array&& val) noexcept; // (9)
|
||||
|
||||
json(const object& val); // (10)
|
||||
|
||||
json(object&& val) noexcept; // (11)
|
||||
|
||||
template <class T>
|
||||
json(const T& val); // (12)
|
||||
|
||||
template <class T>
|
||||
json(const T& val, const allocator_type& allocator); // (13)
|
||||
|
||||
json(const char* val); // (14)
|
||||
|
||||
json(const char* val, const allocator_type& allocator); // (15)
|
||||
|
||||
json(const byte_string_view& bs,
|
||||
semantic_tag tag = semantic_tag::none); // (16)
|
||||
|
||||
json(const byte_string_view& bs,
|
||||
semantic_tag tag = semantic_tag::none,
|
||||
const allocator_type& allocator); // (17)
|
||||
|
||||
json(const bignum& n); // (18)
|
||||
|
||||
json(const bignum& n, const allocator_type& allocator); // (19)
|
||||
```
|
||||
|
||||
(1) Constructs a `json` value that holds an empty json object.
|
||||
|
||||
(2) Constructs a `json` value that holds a json object.
|
||||
|
||||
(3) Constructs a `json` array with the elements of the initializer-list `init`.
|
||||
|
||||
(4) Constructs a copy of val
|
||||
|
||||
(5) Copy with allocator
|
||||
|
||||
(6) Acquires the contents of val, leaving val a `null` value
|
||||
|
||||
(7) Move with allocator
|
||||
|
||||
(8) Constructs a `json` value from a json array
|
||||
|
||||
(9) Acquires the contents of a json array
|
||||
|
||||
(10) Constructs a `json` value from a json object
|
||||
|
||||
(11) Acquires the contents of a json object
|
||||
|
||||
(12) Constructs a `json` value for types supported in [json_type_traits](json_type_traits.md).
|
||||
|
||||
(13) Constructs a `json` value for types supported in [json_type_traits](json_type_traits.md) with allocator.
|
||||
|
||||
(14) Constructs a `json` value for a text string.
|
||||
|
||||
(15) Constructs a `json` value for a text string with supplied allocator.
|
||||
|
||||
(16) Constructs a `json` value for a [byte_string](../byte_string.md).
|
||||
|
||||
(17) Constructs a `json` value for a [byte_string](../byte_string.md) with supplied allocator.
|
||||
|
||||
(18) Constructs a `json` value for a [bignum](../bignum.md).
|
||||
|
||||
(19) Constructs a `json` value for a [bignum](../bignum.md) with supplied allocator.
|
||||
|
||||
### Examples
|
||||
|
||||
```c++
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <jsoncons/json.hpp>
|
||||
|
||||
using namespace jsoncons;
|
||||
int main()
|
||||
{
|
||||
json j1; // An empty object
|
||||
std::cout << "(1) " << j1 << std::endl;
|
||||
|
||||
json j2 = json::object({{"baz", "qux"}, {"foo", "bar"}}); // An object
|
||||
std::cout << "(2) " << j2 << std::endl;
|
||||
|
||||
json j3 = json::array({"bar", "baz"}); // An array
|
||||
std::cout << "(3) " << j3 << std::endl;
|
||||
|
||||
json j4(json::null()); // A null value
|
||||
std::cout << "(4) " << j4 << std::endl;
|
||||
|
||||
json j5(true); // A boolean value
|
||||
std::cout << "(5) " << j5 << std::endl;
|
||||
|
||||
double x = 1.0/7.0;
|
||||
|
||||
json j6(x); // A double value
|
||||
std::cout << "(6) " << j6 << std::endl;
|
||||
|
||||
json j7(x,4); // A double value with specified precision
|
||||
std::cout << "(7) " << j7 << std::endl;
|
||||
|
||||
json j8("Hello"); // A text string
|
||||
std::cout << "(8) " << j8 << std::endl;
|
||||
|
||||
const uint8_t bs[] = {'H','e','l','l','o'};
|
||||
json j9(byte_string("Hello")); // A byte string
|
||||
std::cout << "(9) " << j9 << std::endl;
|
||||
|
||||
std::vector<int> v = {10,20,30};
|
||||
json j10 = v; // From a sequence container
|
||||
std::cout << "(10) " << j10 << std::endl;
|
||||
|
||||
std::map<std::string, int> m{ {"one", 1}, {"two", 2}, {"three", 3} };
|
||||
json j11 = m; // From an associative container
|
||||
std::cout << "(11) " << j11 << std::endl;
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
(1) {}
|
||||
(2) {"baz":"qux","foo":"bar"}
|
||||
(3) ["bar","baz"]
|
||||
(4) null
|
||||
(5) true
|
||||
(6) 0.142857142857143
|
||||
(7) 0.1429
|
||||
(8) "Hello"
|
||||
(9) "SGVsbG8_"
|
||||
(10) [10,20,30]
|
||||
(11) {"one":1,"three":3,"two":2}
|
||||
```
|
|
@ -1,9 +0,0 @@
|
|||
### `jsoncons::json::json`
|
||||
|
||||
```c++
|
||||
~json();
|
||||
```
|
||||
|
||||
Destroys all values and deletes all memory allocated for strings, arrays, and objects.
|
||||
|
||||
|