jsoncons is a C++, header-only library for constructing JSON and JSON-like data formats such as CBOR. It supports
-
Parsing JSON-like text or binary data into an unpacked representation (
jsoncons::basic_json
) that defines an interface for accessing and modifying that data (covers bignum and byte string values.) -
Serializing the unpacked representation into different JSON-like text or binary data.
-
Converting from JSON-like text or binary data to C++ objects and back via json_type_traits.
-
Streaming JSON read and write events, somewhat analogously to SAX (push parsing) and StAX (pull parsing) in the XML world.
It is distributed under the Boost Software License.
jsoncons uses some features that are new to C++ 11, including move semantics and the AllocatorAwareContainer concept. It is tested in continuous integration on AppVeyor and Travis with vs2015 and vs2017 on Windows 10, GCC 4.8 and later on Ubuntu, clang 3.8 and later on Ubuntu, and clang xcode 6.4 and later on OSX.
Download the latest release 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.
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 for the status of old names. The deprecated names can be suppressed by defining macro JSONCONS_NO_DEPRECATED
, which is recommended for new code.
json_benchmarks provides some measurements about how jsoncons
compares to other json
libraries.
- jsonpointer implements the IETF standard JavaScript Object Notation (JSON) Pointer
- jsonpatch implements the IETF standard JavaScript Object Notation (JSON) Patch
- jsonpath implements Stefan Goessner's JSONPath. It also supports search and replace using JSONPath expressions.
- cbor implements decode from and encode to the IETF standard Concise Binary Object Representation (CBOR). It also supports a set of operations for iterating over and accessing the nested data items of a packed CBOR value.
- msgpack implements decode from and encode to the MessagePack binary serialization format.
- csv implements reading (writing) JSON values from (to) CSV files
Planned new features are listed on the roadmap
#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";
// Get reference to object member
const json& val = j["Image Sizing"];
// Access member as double
std::cout << "(2) " << "Dimension 1 = " << val["Dimension 1"].as<double>() << "\n\n";
// Try access member with default
std::cout << "(3) " << "Dimension 2 = " << val.get_with_default("Dimension 2",0.0) << "\n";
}
Output:
(1)
{
"File Format Options": {
"Color Spaces": ["sRGB","AdobeRGB","ProPhoto RGB"]
},
"Image Sizing": {
"Dimension 1": 9.84,
"Resize To Fit": true,
"Resize Unit": "pixels",
"Resize What": "long_edge"
}
}
(2) Dimension 1 = 9.84
(3) Dimension 2 = 0.0
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 an unpacked representation
of JSON-like string or binary data formats, and defines an interface for accessing and modifying that data.
typedef basic_json<char,
ImplementationPolicy = sorted_policy,
Allocator = std::allocator<char>> json;
The library includes four instantiations of basic_json
:
-
json constructs a utf8 character json value that sorts name-value members alphabetically
-
ojson constructs a utf8 character json value that preserves the original name-value insertion order
-
wjson constructs a wide character json value that sorts name-value members alphabetically
-
wojson constructs a wide character json value that preserves the original name-value insertion order
#include <jsoncons/json.hpp>
#include <jsoncons_ext/cbor/cbor_serializer.hpp>
#include <jsoncons_ext/cbor/cbor_view.hpp>
#include <jsoncons_ext/jsonpointer/jsonpointer.hpp>
#include <jsoncons_ext/csv/csv_serializer.hpp>
// For convenience
using namespace jsoncons;
int main()
{
// Construct some CBOR using the streaming API
std::vector<uint8_t> b;
cbor::cbor_bytes_serializer bserializer(b);
bserializer.begin_document();
bserializer.begin_array(); // indefinite length array
bserializer.begin_array(3); // fixed length array
bserializer.string_value("Toronto");
bserializer.byte_string_value({'H','e','l','l','o'});
bserializer.bignum_value("-18446744073709551617");
bserializer.end_array();
bserializer.end_array();
bserializer.end_document();
// Print bytes
std::cout << "(1)\n";
for (auto x : b)
{
std::cout << std::hex << (int)x;
}
std::cout << "\n\n";
cbor::cbor_view bv = b; // a non-owning view of the CBOR bytes
// Loop over the outer array elements
std::cout << "(2)\n";
for (cbor::cbor_view row : bv.array_range())
{
std::cout << row << "\n";
}
std::cout << "\n";
// Get element at position /0/1 using jsonpointer::get on cbor_view (returns value)
cbor::cbor_view val = jsonpointer::get(bv, "/0/1");
std::cout << "(3) " << val.as<std::string>() << "\n\n";
// Print JSON representation with default options
std::cout << "(4)\n";
std::cout << pretty_print(bv) << "\n\n";
// Print JSON representation with different options
json_serializing_options options;
options.byte_string_format(byte_string_chars_format::base64)
.bignum_format(bignum_chars_format::base64url);
std::cout << "(5)\n";
std::cout << pretty_print(bv, options) << "\n\n";
// Unpack bytes into a json variant like structure, and add some more elements
json j = cbor::decode_cbor<json>(bv);
j[0].push_back(bignum("18446744073709551616"));
j[0].insert(j[0].array_range().begin(),10.5);
std::cout << "(6)\n";
std::cout << pretty_print(j) << "\n\n";
// Get element at position /0/0 using jsonpointer::get on json (returns reference)
json& ref = jsonpointer::get(j, "/0/0");
std::cout << "(7) " << ref.as<double>() << "\n\n";
// Repack bytes
std::vector<uint8_t> b2;
cbor::encode_cbor(j, b2);
std::cout << "(8)\n";
cbor::cbor_view b2v = b2;
std::cout << pretty_print(b2v) << "\n\n";
// Serialize to CSV
csv::csv_serializing_options csv_options;
csv_options.column_names("A,B,C,D,E");
std::string from_unpacked;
csv::encode_csv(j, from_unpacked, csv_options);
std::cout << "(9)\n";
std::cout << from_unpacked << "\n\n";
std::string from_packed;
csv::encode_csv(b2v, from_packed, csv_options);
std::cout << "(10)\n";
std::cout << from_packed << "\n\n";
}
Output:
(1)
9f8367546f726f6e746f4548656c6c6fc349100000000ff
(2)
["Toronto","SGVsbG8","-18446744073709551617"]
(3) SGVsbG8
(4)
[
["Toronto","SGVsbG8","-18446744073709551617"]
]
(5)
[
["Toronto","SGVsbG8=","~AQAAAAAAAAAA"]
]
(6)
[
[10.5,"Toronto","SGVsbG8","-18446744073709551617","18446744073709551616"]
]
(7) 10.5
(8)
[
[10.5,"Toronto","SGVsbG8","-18446744073709551617","18446744073709551616"]
]
(9)
A,B,C,D,E
10.5,Toronto,SGVsbG8,-18446744073709551617,18446744073709551616
(10)
A,B,C,D,E
10.5,Toronto,SGVsbG8,-18446744073709551617,18446744073709551616
std::vector<int> v{1, 2, 3, 4};
json j(v);
std::cout << "(1) "<< j << std::endl;
std::deque<int> d = j.as<std::deque<int>>();
std::map<std::string,int> m{{"one",1},{"two",2},{"three",3}};
json j(m);
std::cout << "(2) " << j << std::endl;
std::unordered_map<std::string,int> um = j.as<std::unordered_map<std::string,int>>();
Output:
(1) [1,2,3,4]
(2) {"one":1,"three":3,"two":2}
See json_type_traits
Convert unpacked json
values to user defined types and back (also standard library containers of user defined types)
struct book
{
std::string author;
std::string title;
double price;
};
namespace jsoncons
{
template<class Json>
struct json_type_traits<Json, book>
{
// Implement static functions is, as and to_json
};
}
book book1{"Haruki Murakami", "Kafka on the Shore", 25.17};
book book2{"Charles Bukowski", "Women: A Novel", 12.0};
std::vector<book> v{book1, book2};
json j = v;
std::list<book> l = j.as<std::list<book>>();
See Type Extensibility for details.
The functions decode_json
and encode_json
convert JSON
formatted strings to C++ objects and back. These functions attempt to
perform the conversion by streaming json read and write events with the help of 'json_convert_traits', and if
that is not supported, fall back to using json_type_traits
. decode_json
and encode_json
will work for all C++ classes that have json_type_traits
defined.
#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::string s;
jsoncons::encode_json(employees, s, jsoncons::indenting::indent);
std::cout << "(1)\n" << s << std::endl;
auto employees2 = jsoncons::decode_json<employee_collection>(s);
std::cout << "\n(2)\n";
for (const auto& pair : employees2)
{
std::cout << pair.first << ": " << std::get<1>(pair.second) << std::endl;
}
}
Output:
(1)
{
"Jane Doe": ["Commission","Sales",20000.0],
"John Smith": ["Hourly","Software Engineer",10000.0]
}
(2)
Jane Doe: Sales
John Smith: Software Engineer
decode_json
and encode_json
are supported for many standard library types, and for
user defined types
See decode_json and encode_json
#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_serializer serializer(std::cout, jsoncons::indenting::indent); // pretty print
serializer.begin_document();
serializer.begin_array();
for (const auto& book : some_books.array_range())
{
book.dump_fragment(serializer);
}
for (const auto& book : more_books.array_range())
{
book.dump_fragment(serializer);
}
serializer.end_array();
serializer.end_document();
}
Output:
[
{
"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"
}
]
#include <jsoncons/json_event_reader.hpp>
#include <string>
#include <sstream>
int main()
{
std::string s = R"(
[
{
"enrollmentNo" : 100,
"firstName" : "Tom",
"lastName" : "Cochrane",
"mark" : 55
},
{
"enrollmentNo" : 101,
"firstName" : "Catherine",
"lastName" : "Smith",
"mark" : 95
},
{
"enrollmentNo" : 102,
"firstName" : "William",
"lastName" : "Skeleton",
"mark" : 60
}
]
)";
std::istringstream is(s);
json_event_reader event_reader(is);
for (; !event_reader.done(); event_reader.next())
{
const auto& event = event_reader.current();
switch (event.event_type())
{
case json_event_type::name:
std::cout << event.as<std::string>() << ": ";
break;
case json_event_type::string_value:
std::cout << event.as<std::string>() << "\n";
break;
case json_event_type::int64_value:
case json_event_type::uint64_value:
std::cout << event.as<std::string>() << "\n";
break;
}
}
}
Output:
enrollmentNo: 100
firstName: Tom
lastName: Cochrane
mark: 55
enrollmentNo: 101
firstName: Catherine
lastName: Smith
mark: 95
enrollmentNo: 102
firstName: William
lastName: Skeleton
mark: 60
CMake 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. On Linux it is usually available as a package, e.g., on Ubuntu,
sudo apt-get install cmake
Instructions for building the test suite with CMake may be found in
jsoncons/tests/build/cmake/README.txt
Instructions for building the examples with CMake may be found in
jsoncons/examples/build/cmake/README.txt
Compiler | Version | Architecture | Operating System | Notes |
---|---|---|---|---|
VS | vs2015 | x86,x64 | Windows 10 | |
vs2017 | x86,x64 | Windows 10 | ||
g++ | 4.8 | x64 | Ubuntu | std::regex isn't fully implemented in 4.8, so jsoncons::jsonpath regular expression filters aren't supported |
6 | x64 | Ubuntu | ||
7 | x64 | Ubuntu | ||
8 | x64 | Ubuntu | ||
clang | 3.8 | x64 | Ubuntu | |
5.0 | x64 | Ubuntu | ||
6.0 | x64 | Ubuntu | ||
clang xcode | 6.4 | x64 | OSX | |
7.3 | x64 | OSX | ||
8 | x64 | OSX | ||
8.1 | x64 | OSX | ||
8.2 | x64 | OSX | ||
8.3 | x64 | OSX | ||
9 | x64 | OSX | ||
9.1 | x64 | OSX | ||
9.2 | x64 | OSX | ||
9.3 | x64 | OSX | ||
9.4 | x64 | OSX |
Special thanks to our contributors