Merge branch 'refactor_knowhere' into 'branch-0.5.0'

MS-565 Refactor knowhere

See merge request megasearch/milvus!632

Former-commit-id: bc42aef029e853c270141d5a5727fed0c4f624fe
pull/191/head
jinhai 2019-09-27 16:12:05 +08:00
commit 81c37afc40
784 changed files with 1091 additions and 92357 deletions

View File

@ -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()

View File

@ -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}/

View File

@ -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]);
}

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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) {

View File

@ -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);
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -118,8 +118,8 @@ CPUKDTRNG::Add(const DatasetPtr &origin, const Config &add_config) {
void
CPUKDTRNG::SetParameters(const Config &config) {
for (auto &para : 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);
}
}

View File

@ -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");
}

View File

@ -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"

View File

@ -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");
}
}
}

View File

@ -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

View File

@ -35,7 +35,7 @@ KDTParameterMgr::KDTParameterMgr() {
{"NumTopDimensionKDTSplit", "5"},
{"NumSamplesKDTSplitConsideration", "100"},
{"TPTNumber", "32"},
{"TPTNumber", "1"},
{"TPTLeafSize", "2000"},
{"NumTopDimensionTPTSplit", "5"},

View File

@ -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})

View File

@ -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);
}
}

View File

@ -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);
}
};

View File

@ -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);
}

View File

@ -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;"
]
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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})

File diff suppressed because it is too large Load Diff

View File

@ -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.

View File

@ -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!"_
_"Im 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)

View File

@ -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`

View File

@ -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

View File

@ -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

View File

@ -1,5 +0,0 @@
#!/bin/bash -x
INSTALL_PREFIX=$(pwd)/../build
cp -rf include/* ${INSTALL_PREFIX}/include

View File

@ -1,7 +0,0 @@
#
# Global Configuration for MacOS platform
#
# customize compiler flags
## Add new flags

View File

@ -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")

View File

@ -1,6 +0,0 @@
#
# Global Configuration for windows platform
#
# define some preprocessor flags
add_definitions(/DWIN32_LEAN_AND_MEAN /D_UNICODE /DUNICODE /W4)

View File

@ -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()

File diff suppressed because it is too large Load Diff

View File

@ -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)

View File

@ -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).

View File

@ -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"
]
```

View File

@ -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
},
{}
]
]
```

View File

@ -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"]
```

View File

@ -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

View File

@ -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"
```

View File

@ -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"
```

View File

@ -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)

View File

@ -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
```

View File

@ -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 [Bin­ary JSON](http://bsonspec.org/) data format.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -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>

View File

@ -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 [Bin­ary JSON](http://bsonspec.org/) data format to a json value.

View File

@ -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_"
```

View File

@ -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"
```

View File

@ -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 |&#160;
null | undefined | undefined |&#160;
bool | | true or false |&#160;
int64 | | unsigned or negative integer |&#160;
int64 | timestamp | unsigned or negative integer | 1 (epoch-based date/time)
uint64 | | unsigned integer |&#160;
uint64 | timestamp | unsigned integer | 1 (epoch-based date/time)
double | | half-precision float, float, or double |&#160;
double | timestamp | double | 1 (epoch-based date/time)
string | | string |&#160;
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 |&#160;
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 |&#160;
object | | map |&#160;
### 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
```

View File

@ -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

View File

@ -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;

View File

@ -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
```

View File

@ -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)

View File

@ -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.

View File

@ -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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

View File

@ -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>

View File

@ -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.

View File

@ -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.

View File

@ -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
```

View File

@ -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;

View File

@ -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;

View File

@ -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,
```

View File

@ -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)

View File

@ -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"]
]
]
```

View File

@ -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"]]
}
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

View File

@ -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>

View File

@ -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
```

View File

@ -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 |&#160;
null | undefined | undefined |&#160;
bool | | true or false |&#160;
int64 | | unsigned or negative integer |&#160;
int64 | timestamp | unsigned or negative integer | 1 (epoch-based date/time)
uint64 | | unsigned integer |&#160;
uint64 | timestamp | unsigned integer | 1 (epoch-based date/time)
double | | half-precision float, float, or double |&#160;
double | timestamp | double | 1 (epoch-based date/time)
string | | string |&#160;
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 |&#160;
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 |&#160;
object | | map |&#160;
### 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
]
```

View File

@ -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)

View File

@ -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`

View File

@ -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>&#x2713;</em> indicates that the old name is still supported.
Component or location|Old name, now deprecated|<em>&#x2713;</em>|New name
--------|-----------|--------------|------------------------
class parse_error|`parse_error`|<em>&#x2713;</em>|`serialization_error`
class basic_json|`object_iterator`|<em>&#x2713;</em>|`object_iterator_type`
class basic_json|`const_object_iterator`|<em>&#x2713;</em>|`const_object_iterator_type`
class basic_json|`array_iterator`|<em>&#x2713;</em>|`array_iterator_type`
class basic_json|`const_array_iterator`|<em>&#x2713;</em>|`const_array_iterator_type`
class basic_json|add(size_t index, const json& val)|<em>&#x2713;</em>|`insert(array_iterator pos, const json& val)`
class basic_json|add(size_t index, json&& val)|<em>&#x2713;</em>|`insert(array_iterator pos, json&& val)`
class basic_json|dump_body|<em>&#x2713;</em>|`dump`
class basic_json|remove_range(size_t from_index, size_t to_index)|<em>&#x2713;</em>|`erase(array_iterator first, array_iterator last)`
class basic_json|remove(const std::string& name)|<em>&#x2713;</em>|`erase(const string_view_type& name)`
class basic_json|parse_stream(std::istream& is)|<em>&#x2713;</em>|`parse(std::istream& is)`
class basic_json|parse_stream(std::istream& is, parse_error_handler& err_handler)|<em>&#x2713;</em>|`parse(std::istream& is, parse_error_handler& err_handler)`
class basic_json|as_int() const|<em>&#x2713;</em>|`as<int>`
class basic_json|as_uint() const|<em>&#x2713;</em>|`as<unsigned int>`
class basic_json|as_long() const|<em>&#x2713;</em>|`as<long>`
class basic_json|as_ulong() const|<em>&#x2713;</em>|`as<unsigned long>`
class basic_json|as_longlong() const|<em>&#x2713;</em>|`as<long long>`
class basic_json|as_ulonglong() const|<em>&#x2713;</em>|`as<unsigned long long>`
class basic_json|is_longlong() const|<em>&#x2713;</em>|is<long long>()
class basic_json|is_ulonglong() const|<em>&#x2713;</em>|is<unsigned long long>()
class basic_json|is_numeric() const|<em>&#x2713;</em>|`is_number()`
class basic_json|remove_member(const std::string& name)|<em>&#x2713;</em>|erase(const string_view_type& name)
class basic_json|const json& get(const std::string& name) const|<em>&#x2713;</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>&#x2713;</em>|Use `contains(const string_view_type& name)`
class basic_json|has_key(const std::string& name) const|<em>&#x2713;</em>|Use `contains(const string_view_type& name)`
class basic_json|add|<em>&#x2713;</em>|`push_back`
class basic_json|set|<em>&#x2713;</em>|`insert_or_assign`
class basic_json|members()|<em>&#x2713;</em>|object_range()
class basic_json|elements()|<em>&#x2713;</em>|array_range()
class basic_json|begin_members()|<em>&#x2713;</em>|Use object_range().begin()
class basic_json|end_members()|<em>&#x2713;</em>|Use object_range().end()
class basic_json|begin_elements()|<em>&#x2713;</em>|Use array_range().begin()
class basic_json|end_elements()|<em>&#x2713;</em>|Use array_range().end()
class basic_json|is_empty() const|<em>&#x2713;</em>|`empty()`
class basic_json|parse_string(const std::string& s)|<em>&#x2713;</em>|parse(const std::string& s)
class basic_json|parse_string(const std::string& s,parse_error_handler& err_handler)|<em>&#x2713;</em>|Use parse(const std::string& s,parse_error_handler& err_handler)
class basic_json|resize_array(size_t n)|<em>&#x2713;</em>|resize(size_t n)
class basic_json|resize_array(size_t n, const json& val)|<em>&#x2713;</em>|resize(size_t n, const json& val)
class basic_json|to_stream|<em>&#x2713;</em>|Use dump
class basic_json|write|<em>&#x2713;</em>|Use dump
class basic_json|`json` initializer-list constructor||Construct from `json::array` with initializer-list
class basic_json_deserializer|json_deserializer|<em>&#x2713;</em>|Use json_decoder<json>`
class basic_json_deserializer|wjson_deserializer|<em>&#x2713;</em>|Use `json_decoder<wjson>`
class basic_json_deserializer|ojson_deserializer|<em>&#x2713;</em>|Use `json_decoder<ojson>`
class basic_json_deserializer|wojson_deserializer|<em>&#x2713;</em>|Use `json_decoder<wojson>`
class basic_json|owjson|<em>&#x2713;</em>|wojson`
class basic_json|member_type name()|<em>&#x2713;</em>|key()
class basic_json|rename_name_filter|<em>&#x2713;</em>|rename_object_member_filter`
class basic_json|any||removed
class basic_json|member_type|<em>&#x2713;</em>|key_value_pair_type
class basic_json|kvp_type|<em>&#x2713;</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>&#x2713;</em>|get_result()
class json_content_handler|begin_json|<em>&#x2713;</em>|Removed
class json_content_handler|end_json|<em>&#x2713;</em>|`flush`
class json_content_handler|begin_document|<em>&#x2713;</em>|Removed
class json_content_handler|end_document|<em>&#x2713;</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>&#x2713;</em>|`json_serializing_options`
class serialization_options|`serialization_options`|<em>&#x2713;</em>|Use `json_serializing_options`
class json_reader|max_depth(),max_depth(value)|<em>&#x2713;</em>|Use `json_serializing_options::max_nesting_depth`
class json_reader|max_nesting_depth(),max_nesting_depth(value)|<em>&#x2713;</em>|Use `json_serializing_options::max_nesting_depth`
class json_reader|json_input_handler& parent()|<em>&#x2713;</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)`|&#160;|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)
&#160;|do_ulonglong_value(unsigned long long value)||Removed, override do_uinteger_value(uint64_t value)
&#160;|do_double_value(double value)||Removed, override do_double_value(double value, uint8_t precision)
&#160;|`value(value)`|<em>&#x2713;</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>&#x2713;</em>|Use current_char()
json_filter|parent()|<em>&#x2713;</em>|Use downstream_handler()
&#160;|input_handler()|<em>&#x2713;</em>|Use downstream_handler()
file `csv_parameters.hpp`|&#160;||Use `csv_options.hpp`
file `csv_serializing_options.hpp`|&#160;||Use `csv_serializing_options.hpp`
class `csv_parameters`|`csv_parameters`|&#160;|Use `csv_serializing_options`
class `csv_serializing_options`|`csv_parameters`|&#160;|Use `csv_options`
class `csv_options`|`header(std::string value)`|&#160;|Use `column_names(const std::string& value)`
class `csv_options`|`column_names(std::vector<std::string>> value)`|<em>&#x2713;</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>&#x2713;</em>|Use `column_types(const std::string& value)`
class `csv_options`|`column_defaults(std::vector<std::string>> value)`|<em>&#x2713;</em>|Use `column_defaults(const std::string& value)`
file `output_format.hpp`|&#160;|&#160;|Use `json_serializing_options.hpp`
file `json_serializing_options`.hpp|&#160;|&#160;|Use `json_options.hpp`
class json_options|`array_array_block_option accessor and modifier` accessor and modifier|&#160;|Use `array_array_line_splits` accessor and modifier
class json_options|`array_object_block_option accessor and modifier`|&#160;|Use `array_object_line_splits` accessor and modifier
class json_options|`object_array_block_option accessor and modifier`|&#160;|Use `object_array_line_splits` accessor and modifier
class json_options|`object_object_line_splits accessor and modifier`|&#160;|Use `object_object_line_splits` accessor and modifier
class json_options|`array_array_line_splits accessor and modifier` accessor and modifier|<em>&#x2713;</em>|Use `array_array_line_splits` accessor and modifier
class json_options|`array_object_line_splits accessor and modifier`|<em>&#x2713;</em>|Use `array_object_line_splits` accessor and modifier
class json_options|`object_array_line_splits accessor and modifier`|<em>&#x2713;</em>|Use `object_array_line_splits` accessor and modifier
class json_options|`object_object_line_splits accessor and modifier`|<em>&#x2713;</em>|Use `object_object_line_splits` accessor and modifier
msgpack|`jsoncons_ext/msgpack/message_pack.hpp` header file|<em>&#x2713;</em>|Use `jsoncons_ext/msgpack/msgpack.hpp`
&#160;|`encode_message_pack`|<em>&#x2713;</em>|Use `encode_msgpack`
&#160;|`decode_message_pack`|<em>&#x2713;</em>|Use `decode_msgpack`

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

View File

@ -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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

View File

@ -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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

View File

@ -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>

View File

@ -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)

View File

@ -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)

View File

@ -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"
}
]
}
```

View File

@ -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
```

View File

@ -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
```

View File

@ -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}
```

View File

@ -1,9 +0,0 @@
### `jsoncons::json::json`
```c++
~json();
```
Destroys all values and deletes all memory allocated for strings, arrays, and objects.

Some files were not shown because too many files have changed in this diff Show More