A C++, header-only library for constructing JSON and JSON-like data formats, with JSON Pointer, JSON Patch, JSON Schema, JSONPath, JMESPath, CSV, MessagePack, CBOR, BSON, UBJSON

JSONCONS

jsoncons is a C++, header-only library for constructing JSON and JSON-like data formats such as CBOR. For each supported data format, it enables you to work with the data in a number of ways:

  • As a variant-like data structure, basic_json

  • As a strongly typed C++ data structure that implements json_type_traits

  • With cursor-level access to a stream of parse events, somewhat analogous to StAX pull parsing and push serializing 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. It supports reading an entire JSON text in memory in a variant-like structure. But it also supports efficient access to the underlying data using StAX-style pull parsing and push serializing. And it supports incremental parsing into a user's preferred form, using information about user types provided by specializations of json_type_traits.

The jsoncons data model supports the familiar JSON types - nulls, booleans, numbers, strings, arrays, objects - plus byte strings. In addition, jsoncons supports semantic tagging of datetimes, epoch times, big integers, big decimals, big floats 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.

jsoncons is free but welcomes support to sustain its development. If you find this library helpful, please consider making a one time donation or becoming a ❤️ sponsor.

Extensions

What users say

"I am so happy I have come across your json c++ library!"

"I’m using your library for an external interface to pass data, as well as using the conversions from csv to json, which are really helpful for converting data for use in javascript"

"Verified that, for my needs in JSON and CBOR, it is working perfectly"

"the ability to have an xpath like facility is so useful"

"I finally decided on jsoncons after evaluating quite a few json libraries out there."

"the serialization lib of choice with its beautiful mappings and ease of use"

"really good" "awesome project" "very solid and very dependable" "my team loves it" "Your repo rocks!!!!!"

Get jsoncons

You can use the vcpkg platform library manager to install the jsoncons package.

Or, 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.

How to use it

The library requires a C++ Compiler with C++11 support. In addition the library defines jsoncons::endian, jsoncons::basic_string_view, jsoncons::optional, and jsoncons::span, which will be typedefed to their standard library equivalents if detected. Otherwise they will be typedefed to internal, C++11 compatible, implementations.

The library uses exceptions and in some cases std::error_code's to report errors. Apart from jsoncons::assertion_error, all jsoncons exception classes implement the jsoncons::json_error interface. If exceptions are disabled or if the compile time macro JSONCONS_NO_EXCEPTIONS is defined, throws become calls to std::terminate.

Benchmarks

json_benchmarks provides some measurements about how jsoncons compares to other json libraries.

JSONPath Comparison shows how jsoncons JsonPath compares with other implementations

Examples

Working with JSON data

Working with CBOR data

Working with JSON data

For the examples below you need to include some header files and initialize a string of JSON data:

#include <jsoncons/json.hpp>
#include <jsoncons_ext/jsonpath/jsonpath.hpp>
#include <iostream>

using namespace jsoncons; // for convenience

std::string data = R"(
    {
       "application": "hiking",
       "reputons": [
       {
           "rater": "HikingAsylum",
           "assertion": "advanced",
           "rated": "Marilyn C",
           "rating": 0.90,
           "generated": 1514862245
         }
       ]
    }
)";

jsoncons allows you to work with the data in a number of ways:

As a variant-like data structure

int main()
{
    // Parse the string of data into a json value
    json j = json::parse(data);

    // Does object member reputons exist?
    std::cout << "(1) " << std::boolalpha << j.contains("reputons") << "\n\n";

    // Get a reference to reputons array 
    const json& v = j["reputons"]; 

    // Iterate over reputons array 
    std::cout << "(2)\n";
    for (const auto& item : v.array_range())
    {
        // Access rated as string and rating as double
        std::cout << item["rated"].as<std::string>() << ", " << item["rating"].as<double>() << "\n";
    }
    std::cout << "\n";

    // Select all "rated" with JSONPath
    std::cout << "(3)\n";
    json result = jsonpath::json_query(j,"$..rated");
    std::cout << pretty_print(result) << "\n\n";

    // Serialize back to JSON
    std::cout << "(4)\n" << pretty_print(j) << "\n\n";
}

Output:

(1) true

(2)
Marilyn C, 0.9

(3)
[
    "Marilyn C"
]

(4)
{
    "application": "hiking",
    "reputons": [
        {
            "assertion": "advanced",
            "generated": 1514862245,
            "rated": "Marilyn C",
            "rater": "HikingAsylum",
            "rating": 0.9
        }
    ]
}

As a strongly typed C++ data structure

jsoncons supports transforming JSON texts into C++ data structures. The functions decode_json and encode_json convert strings or streams of JSON data to C++ data structures and back. Decode and encode work for all C++ classes that have json_type_traits defined. jsoncons already supports many types in the standard library, and your own types will be supported too if you specialize json_type_traits in the jsoncons namespace.

namespace ns {
    enum class hiking_experience {beginner,intermediate,advanced};

    class hiking_reputon
    {
        std::string rater_;
        hiking_experience assertion_;
        std::string rated_;
        double rating_;
        std::optional<std::chrono::seconds> generated_; // assumes C++17, if not use jsoncons::optional
        std::optional<std::chrono::seconds> expires_;
    public:
        hiking_reputon(const std::string& rater,
                       hiking_experience assertion,
                       const std::string& rated,
                       double rating,
                       const std::optional<std::chrono::seconds>& generated = 
                           std::optional<std::chrono::seconds>(),
                       const std::optional<std::chrono::seconds>& expires = 
                           std::optional<std::chrono::seconds>())
            : rater_(rater), assertion_(assertion), rated_(rated), rating_(rating),
              generated_(generated), expires_(expires)
        {
        }

        const std::string& rater() const {return rater_;}
        hiking_experience assertion() const {return assertion_;}
        const std::string& rated() const {return rated_;}
        double rating() const {return rating_;}
        std::optional<std::chrono::seconds> generated() const {return generated_;}
        std::optional<std::chrono::seconds> expires() const {return expires_;}

        friend bool operator==(const hiking_reputon& lhs, const hiking_reputon& rhs)
        {
            return lhs.rater_ == rhs.rater_ && lhs.assertion_ == rhs.assertion_ && 
                   lhs.rated_ == rhs.rated_ && lhs.rating_ == rhs.rating_ &&
                   lhs.confidence_ == rhs.confidence_ && lhs.expires_ == rhs.expires_;
        }

        friend bool operator!=(const hiking_reputon& lhs, const hiking_reputon& rhs)
        {
            return !(lhs == rhs);
        };
    };

    class hiking_reputation
    {
        std::string application_;
        std::vector<hiking_reputon> reputons_;
    public:
        hiking_reputation(const std::string& application, 
                          const std::vector<hiking_reputon>& reputons)
            : application_(application), 
              reputons_(reputons)
        {}

        const std::string& application() const { return application_;}
        const std::vector<hiking_reputon>& reputons() const { return reputons_;}
    };

} // namespace ns

// Declare the traits. Specify which data members need to be serialized.

JSONCONS_ENUM_TRAITS(ns::hiking_experience, beginner, intermediate, advanced)
// First four members listed are mandatory, generated and expires are optional
JSONCONS_N_CTOR_GETTER_TRAITS(ns::hiking_reputon, 4, rater, assertion, rated, rating, 
                              generated, expires)

// All members are mandatory
JSONCONS_ALL_CTOR_GETTER_TRAITS(ns::hiking_reputation, application, reputons)

int main()
{
    // Decode the string of data into a c++ structure
    ns::hiking_reputation v = decode_json<ns::hiking_reputation>(data);

    // Iterate over reputons array value
    std::cout << "(1)\n";
    for (const auto& item : v.reputons())
    {
        std::cout << item.rated() << ", " << item.rating();
        if (item.generated())
        {
            std::cout << ", " << (*item.generated()).count();
        }
        std::cout << "\n";
    }

    // Encode the c++ structure into a string
    std::string s;
    encode_json_pretty(v, s);
    std::cout << "(2)\n";
    std::cout << s << "\n";
}

Output:

(1)
Marilyn C, 0.9, 1514862245
(2)
{
    "application": "hiking",
    "reputons": [
        {
            "assertion": "advanced",
            "generated": 1514862245,
            "rated": "Marilyn C",
            "rater": "HikingAsylum",
            "rating": 0.9
        }
    ]
}

This example makes use of the convenience macros JSONCONS_ENUM_TRAITS, JSONCONS_N_CTOR_GETTER_TRAITS, and JSONCONS_ALL_CTOR_GETTER_TRAITS to specialize the json_type_traits for the enum type ns::hiking_experience, the class ns::hiking_reputon (with some non-mandatory members), and the class ns::hiking_reputation (with all mandatory members.) The macro JSONCONS_ENUM_TRAITS generates the code from the enum identifiers, and the macros JSONCONS_N_CTOR_GETTER_TRAITS and JSONCONS_ALL_CTOR_GETTER_TRAITS generate the code from the get functions and a constructor. These macro declarations must be placed outside any namespace blocks.

See examples for other ways of specializing json_type_traits.

With cursor-level access

A typical pull parsing application will repeatedly process the current() event and call next() to advance to the next event, until done() returns true.

int main()
{
    json_cursor cursor(data);
    for (; !cursor.done(); cursor.next())
    {
        const auto& event = cursor.current();
        switch (event.event_type())
        {
            case staj_event_type::begin_array:
                std::cout << event.event_type() << " " << "\n";
                break;
            case staj_event_type::end_array:
                std::cout << event.event_type() << " " << "\n";
                break;
            case staj_event_type::begin_object:
                std::cout << event.event_type() << " " << "\n";
                break;
            case staj_event_type::end_object:
                std::cout << event.event_type() << " " << "\n";
                break;
            case staj_event_type::key:
                // Or std::string_view, if supported
                std::cout << event.event_type() << ": " << event.get<jsoncons::string_view>() << "\n";
                break;
            case staj_event_type::string_value:
                // Or std::string_view, if supported
                std::cout << event.event_type() << ": " << event.get<jsoncons::string_view>() << "\n";
                break;
            case staj_event_type::null_value:
                std::cout << event.event_type() << "\n";
                break;
            case staj_event_type::bool_value:
                std::cout << event.event_type() << ": " << std::boolalpha << event.get<bool>() << "\n";
                break;
            case staj_event_type::int64_value:
                std::cout << event.event_type() << ": " << event.get<int64_t>() << "\n";
                break;
            case staj_event_type::uint64_value:
                std::cout << event.event_type() << ": " << event.get<uint64_t>() << "\n";
                break;
            case staj_event_type::double_value:
                std::cout << event.event_type() << ": " << event.get<double>() << "\n";
                break;
            default:
                std::cout << "Unhandled event type: " << event.event_type() << " " << "\n";
                break;
        }
    }    
}

Output:

begin_object
key: application
string_value: hiking
key: reputons
begin_array
begin_object
key: rater
string_value: HikingAsylum
key: assertion
string_value: advanced
key: rated
string_value: Marilyn C
key: rating
double_value: 0.9
key: generated
uint64_value: 1514862245
end_object
end_array
end_object

You can apply a filter to a cursor using the pipe syntax (e.g., cursor | filter1 | filter2 | ...)

int main()
{
    std::string name;
    auto filter = [&](const staj_event& ev, const ser_context&) -> bool
    {
        if (ev.event_type() == staj_event_type::key)
        {
            name = ev.get<std::string>();
            return false;
        }
        if (name == "rated")
        {
            name.clear();
            return true;
        }
        return false;
    };

    json_cursor cursor(data);
    auto filtered_c = cursor | filter;

    for (; !filtered_c.done(); filtered_c.next())
    {
        const auto& event = filtered_c.current();
        switch (event.event_type())
        {
            case staj_event_type::string_value:
                // Or std::string_view, if C++17
                std::cout << event.event_type() << ": " << event.get<jsoncons::string_view>() << "\n";
                break;
            default:
                std::cout << "Unhandled event type\n";
                break;
        }
    }
}    

Output:

Marilyn C

Working with CBOR data

For the examples below you need to include some header files and initialize a buffer of CBOR data:

#include <iomanip>
#include <iostream>
#include <jsoncons/json.hpp>
#include <jsoncons_ext/cbor/cbor.hpp>
#include <jsoncons_ext/jsonpath/jsonpath.hpp>

using namespace jsoncons; // for convenience

const std::vector<uint8_t> data = {
    0x9f, // Start indefinte length array
      0x83, // Array of length 3
        0x63, // String value of length 3
          0x66,0x6f,0x6f, // "foo" 
        0x44, // Byte string value of length 4
          0x50,0x75,0x73,0x73, // 'P''u''s''s'
        0xc5, // Tag 5 (bigfloat)
          0x82, // Array of length 2
            0x20, // -1
            0x03, // 3   
      0x83, // Another array of length 3
        0x63, // String value of length 3
          0x62,0x61,0x72, // "bar"
        0xd6, // Expected conversion to base64
        0x44, // Byte string value of length 4
          0x50,0x75,0x73,0x73, // 'P''u''s''s'
        0xc4, // Tag 4 (decimal fraction)
          0x82, // Array of length 2
            0x38, // Negative integer of length 1
              0x1c, // -29
            0xc2, // Tag 2 (positive bignum)
              0x4d, // Byte string value of length 13
                0x01,0x8e,0xe9,0x0f,0xf6,0xc3,0x73,0xe0,0xee,0x4e,0x3f,0x0a,0xd2,
    0xff // "break"
};

jsoncons allows you to work with the CBOR data similarly to JSON data:

As a variant-like data structure

int main()
{
    // Parse the CBOR data into a json value
    json j = cbor::decode_cbor<json>(data);

    // Pretty print
    std::cout << "(1)\n" << pretty_print(j) << "\n\n";

    // Iterate over rows
    std::cout << "(2)\n";
    for (const auto& row : j.array_range())
    {
        std::cout << row[1].as<jsoncons::byte_string>() << " (" << row[1].tag() << ")\n";
    }
    std::cout << "\n";

    // Select the third column with JSONPath
    std::cout << "(3)\n";
    json result = jsonpath::json_query(j,"$[*][2]");
    std::cout << pretty_print(result) << "\n\n";

    // Serialize back to CBOR
    std::vector<uint8_t> buffer;
    cbor::encode_cbor(j, buffer);
    std::cout << "(4)\n" << byte_string_view(buffer) << "\n\n";
}

Output:

(1)
[
    ["foo", "UHVzcw", "0x3p-1"],
    ["bar", "UHVzcw==", "1.23456789012345678901234567890"]
]

(2)
50,75,73,73 (n/a)
50,75,73,73 (base64)

(3)
[
    "0x3p-1",
    "1.23456789012345678901234567890"
]

(4)
82,83,63,66,6f,6f,44,50,75,73,73,c5,82,20,03,83,63,62,61,72,d6,44,50,75,73,73,c4,82,38,1c,c2,4d,01,8e,e9,0f,f6,c3,73,e0,ee,4e,3f,0a,d2

As a strongly typed C++ data structure

int main()
{
    // Parse the string of data into a std::vector<std::tuple<std::string,jsoncons::byte_string,std::string>> value
    auto val = cbor::decode_cbor<std::vector<std::tuple<std::string,jsoncons::byte_string,std::string>>>(data);

    std::cout << "(1)\n";
    for (const auto& row : val)
    {
        std::cout << std::get<0>(row) << ", " << std::get<1>(row) << ", " << std::get<2>(row) << "\n";
    }
    std::cout << "\n";

    // Serialize back to CBOR
    std::vector<uint8_t> buffer;
    cbor::encode_cbor(val, buffer);
    std::cout << "(2)\n" << byte_string_view(buffer) << "\n\n";
}

Output:

(1)
foo, 50,75,73,73, 0x3p-1
bar, 50,75,73,73, 1.23456789012345678901234567890

(2)
82,9f,63,66,6f,6f,44,50,75,73,73,66,30,78,33,70,2d,31,ff,9f,63,62,61,72,44,50,75,73,73,78,1f,31,2e,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,ff

Note that when decoding the bigfloat and decimal fraction into a std::string, we lose the semantic information that the variant like data structure preserved with a tag, so serializing back to CBOR produces a text string.

With cursor-level access

A typical pull parsing application will repeatedly process the current() event and call next() to advance to the next event, until done() returns true.

int main()
{
    cbor::cbor_bytes_cursor cursor(data);
    for (; !cursor.done(); cursor.next())
    {
        const auto& event = cursor.current();
        switch (event.event_type())
        {
            case staj_event_type::begin_array:
                std::cout << event.event_type() << " " << "(" << event.tag() << ")\n";
                break;
            case staj_event_type::end_array:
                std::cout << event.event_type() << " " << "(" << event.tag() << ")\n";
                break;
            case staj_event_type::begin_object:
                std::cout << event.event_type() << " " << "(" << event.tag() << ")\n";
                break;
            case staj_event_type::end_object:
                std::cout << event.event_type() << " " << "(" << event.tag() << ")\n";
                break;
            case staj_event_type::key:
                // Or std::string_view, if supported
                std::cout << event.event_type() << ": " << event.get<jsoncons::string_view>() << " " << "(" << event.tag() << ")\n";
                break;
            case staj_event_type::string_value:
                // Or std::string_view, if supported
                std::cout << event.event_type() << ": " << event.get<jsoncons::string_view>() << " " << "(" << event.tag() << ")\n";
                break;
            case staj_event_type::byte_string_value:
                std::cout << event.event_type() << ": " << event.get<jsoncons::span<const uint8_t>>() << " " << "(" << event.tag() << ")\n";
                break;
            case staj_event_type::null_value:
                std::cout << event.event_type() << " " << "(" << event.tag() << ")\n";
                break;
            case staj_event_type::bool_value:
                std::cout << event.event_type() << ": " << std::boolalpha << event.get<bool>() << " " << "(" << event.tag() << ")\n";
                break;
            case staj_event_type::int64_value:
                std::cout << event.event_type() << ": " << event.get<int64_t>() << " " << "(" << event.tag() << ")\n";
                break;
            case staj_event_type::uint64_value:
                std::cout << event.event_type() << ": " << event.get<uint64_t>() << " " << "(" << event.tag() << ")\n";
                break;
            case staj_event_type::half_value:
            case staj_event_type::double_value:
                std::cout << event.event_type() << ": "  << event.get<double>() << " " << "(" << event.tag() << ")\n";
                break;
            default:
                std::cout << "Unhandled event type " << event.event_type() << " " << "(" << event.tag() << ")\n";
                break;
        }
    }
}

Output:

begin_array (n/a)
begin_array (n/a)
string_value: foo (n/a)
byte_string_value: 50,75,73,73 (n/a)
string_value: 0x3p-1 (bigfloat)
end_array (n/a)
begin_array (n/a)
string_value: bar (n/a)
byte_string_value: 50,75,73,73 (base64)
string_value: 1.23456789012345678901234567890 (bigdec)
end_array (n/a)
end_array (n/a)

You can apply a filter to a cursor using the pipe syntax,

int main()
{
    auto filter = [&](const staj_event& ev, const ser_context&) -> bool
    {
        return (ev.tag() == semantic_tag::bigdec) || (ev.tag() == semantic_tag::bigfloat);  
    };

    cbor::cbor_bytes_cursor cursor(data);
    auto filtered_c = cursor | filter;

    for (; !filtered_c.done(); filtered_c.next())
    {
        const auto& event = filtered_c.current();
        switch (event.event_type())
        {
            case staj_event_type::string_value:
                // Or std::string_view, if supported
                std::cout << event.event_type() << ": " << event.get<jsoncons::string_view>() << " " << "(" << event.tag() << ")\n";
                break;
            default:
                std::cout << "Unhandled event type " << event.event_type() << " " << "(" << event.tag() << ")\n";
                break;
        }
    }
}

Output:

string_value: 0x3p-1 (bigfloat)
string_value: 1.23456789012345678901234567890 (bigdec)

Supported compilers

jsoncons requires a compiler with C++11 support. It is tested in continuous integration on Github Actions, AppVeyor, Travis, and doozer. UndefinedBehaviorSanitizer (UBSan) diagnostics are enabled for selected gcc and clang builds. Since v0.151.0, it is integrated with Google OSS-fuzz, with coverage for all parsers and encoders.

Compiler Version Architecture Operating System Notes
Microsoft Visual Studio vs2015 (MSVC 19.0.24241.7) x86,x64 Windows 10
vs2017 x86,x64 Windows 10
vs2019 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
4.9.2 i386 Debian 8
clang 4.0, 5.0, 6.0, 7, 8, 9, 10 x64 Ubuntu
clang xcode 9.3, 9.4, 10, 10.1, 10.2, 11.2, 12 x64 OSX

Building the test suite and examples with CMake

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

Once cmake is installed, you can build and run the unit tests from the jsoncons directory,

On Windows:

> mkdir build
> cd build
> cmake .. -DJSONCONS_BUILD_TESTS=On
> cmake --build .
> ctest -C Debug --output-on-failure

On UNIX:

$ mkdir build
$ cd build
$ cmake .. -DJSONCONS_BUILD_TESTS=On
$ cmake --build .
$ ctest --output-on-failure

Acknowledgements

jsoncons uses the PVS-Studio static analyzer, provided free for open source projects.

A big thanks to the comp.lang.c++ community for help with implementation details.

The jsoncons platform dependent binary configuration draws on to the excellent MIT licensed tinycbor.

Thanks to Milo Yip, author of RapidJSON, for raising the quality of JSON libraries across the board, by publishing the benchmarks, 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, with minor modifications.

The macro JSONCONS_ALL_MEMBER_TRAITS follows the approach taken by Martin York's ThorsSerializer

Special thanks to our contributors

Comments
  • Question: Serialize and Deserialize performance

    Question: Serialize and Deserialize performance

    Thanks for creating header-only library with jsonpath support. I am planning to use in my LuaJIT based application by adding a C/FFI layer.

    The performance for parse and deserialize using << seem to be much slower (twice) than cjson library's encode and decode function which is currently used in our application.

    e.g I am decoding using

    json obj = json::parse(json_str);

    and encoding using

    std::ostringstream ss;
    ss << *json_payload_;
    strcpy(payload_out, ss.str().c_str());
    

    Any suggestion for optimization?

  • jsonpatch_error() shutdown crash

    jsonpatch_error() shutdown crash

    Hi. I'm getting a weird error trying to catch a jsonpatch_error(). My code is quite simple -

            try {
                        jsoncons::jsonpatch::apply_patch(jsonob->json, delta);
    ...
                } catch ( std::exception& e ) {
    ...
    

    I'm assuming that std::exception is ok here - is that correct ?

    This code works fine normally but sometimes I'm getting this crash during shutdown.

    #0  0x0000003ae9a325e5 in raise () from /lib64/libc.so.6
    #1  0x0000003ae9a33dc5 in abort () from /lib64/libc.so.6
    #2  0x0000000000af6e75 in __gnu_cxx::__verbose_terminate_handler () at ../../../../libstdc++-v3/libsupc++/vterminate.cc:95
    #3  0x0000000000af6a26 in __cxxabiv1::__terminate (handler=<optimized out>) at ../../../../libstdc++-v3/libsupc++/eh_terminate.cc:38
    #4  0x0000000000af6a53 in std::terminate () at ../../../../libstdc++-v3/libsupc++/eh_terminate.cc:48
    #5  0x0000000000af6bcf in __cxxabiv1::__cxa_pure_virtual () at ../../../../libstdc++-v3/libsupc++/pure.cc:50
    #6  0x00000000006a4971 in message (this=<synthetic pointer>) at /usr/include/c++/4.8.5/system_error:158
    #7  std::system_error::system_error ([email protected]=0x7f7e78de5f80, __ec=...) at /usr/include/c++/4.8.5/system_error:316
    #8  0x00000000006b431e in jsonpatch_error (ec=..., this=0x7f7e78de5f80, __in_chrg=<optimized out>, __vtt_parm=<optimized out>)
        at ../../libs/jsoncons/include/jsoncons_ext/jsonpatch/jsonpatch_error.hpp:19
    #9  jsoncons::jsonpatch::apply_patch<jsoncons::basic_json<char, jsoncons::sorted_policy, std::allocator<char> > > (target=...,
        patch=...) at ../../libs/jsoncons/include/jsoncons_ext/jsonpatch/jsonpatch.hpp:487
    

    i.e. It's saying a pure virtual method is being called when the patch errror message is being accessed.

    Also, the patch message being processed is not invalid but is being interpreted as invalid.

    This seems to happen only when we're shutting down the application.

    I noticed that I can call the patch method and pass an errorcode ref and that won't throw an error so I could avoid the crash that way.

  • jmespath::search() segfault on valid query

    jmespath::search() segfault on valid query

    Describe the bug

    For this json

    [
      {
        "name" : "foo", 
        "datasets" : [
          { "name" : "bar", "tissues" : [ { "label" : "baz" }] }
        ]
      },
      {
        "name" : "foo1", 
        "datasets" : [
          { "name" : "bar1", "tissues" : [ { "label" : "baz1" }] }
        ]
      }
    ]
    

    the JMESpath query

    [].{
        collection: name,
        dataset: datasets[].name,
        tissue: datasets[].tissue[*].label
    }
    

    should return a valid object, instead it segfaults with

    jsoncons $ ./test
    zsh: segmentation fault  ./test
    

    Enumerate the steps to reproduce the bug

    Here's a small program demonstrating this

    #include <jsoncons/json.hpp>
    #include <jsoncons_ext/jmespath/jmespath.hpp>
    
    using namespace jsoncons; // for convenience
    
    std::string data = R"(
        [{
          "name" : "foo", 
          "datasets" : [
            { "name" : "bar", "tissues" : [ { "label" : "baz" }] }
          ]
        },
        {
          "name" : "foo1", 
          "datasets" : [
            { "name" : "bar1", "tissues" : [ { "label" : "baz1" }] }
          ]
        }]
    )";
    
    int main()
    {
        std::string path = R"(
            [].{
                collection: name,
                dataset: datasets[].name,
                tissue: datasets[].tissue[*].label
            }
        )";
    
        json j = json::parse(data);
        json result = jmespath::search(j, path);
    
        return 0;
    }
    

    compiled and executed as

    /tmp/jsoncons $ g++ -std=c++14 -g -O0 -I /tmp/jsoncons/include -o test segfault.cpp
    /tmp/jsoncons $ ./test
    zsh: segmentation fault  ./test
    

    Under lldb

    (lldb) run
    Process 5452 launched: '/tmp/jsoncons/test' (x86_64)
    Process 5452 stopped
    * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
        frame #0: 0x000000010000869c test`std::__1::vector<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::allocator<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > > >::size(this=0x0005000100704e58 size=0) const at vector:656:46
       653
       654 	    _LIBCPP_INLINE_VISIBILITY
       655 	    size_type size() const _NOEXCEPT
    -> 656 	        {return static_cast<size_type>(this->__end_ - this->__begin_);}
       657 	    _LIBCPP_INLINE_VISIBILITY
       658 	    size_type capacity() const _NOEXCEPT
       659 	        {return __base::capacity();}
    (lldb) bt
    * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
      * frame #0: 0x000000010000869c test`std::__1::vector<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::allocator<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > > >::size(this=0x0005000100704e58 size=0) const at vector:656:46
        frame #1: 0x0000000100012ece test`jsoncons::json_array<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >::size(this=0x0005000100704e50) const at json_container_types.hpp:137:52
        frame #2: 0x000000010000536c test`jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >::size(this=0x0000000100704c90) const at basic_json.hpp:2403:58
        frame #3: 0x00000001000053bd test`jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >::size(this=0x0000000100704e38) const at basic_json.hpp:2409:72
        frame #4: 0x000000010000b8db test`jsoncons::json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, void>::destroy(this=0x0000000100704da0) at json_container_types.hpp:1217:36
        frame #5: 0x000000010000b7fc test`jsoncons::json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, void>::~json_object(this=0x0000000100704da0) at json_container_types.hpp:647:13
        frame #6: 0x000000010000b7d5 test`jsoncons::json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, void>::~json_object(this=0x0000000100704da0) at json_container_types.hpp:646:9
        frame #7: 0x000000010000b7b9 test`std::__1::allocator<jsoncons::json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, void> >::destroy(this=0x00007ffeefbff1c0, __p=0x0000000100704da0) at memory:1936:64
        frame #8: 0x000000010000b78d test`void std::__1::allocator_traits<std::__1::allocator<jsoncons::json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, void> > >::__destroy<jsoncons::json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, void> >((null)=std::__1::true_type @ 0x00007ffeefbff148, __a=0x00007ffeefbff1c0, __p=0x0000000100704da0) at memory:1798:18
        frame #9: 0x000000010000b75d test`void std::__1::allocator_traits<std::__1::allocator<jsoncons::json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, void> > >::destroy<jsoncons::json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, void> >(__a=0x00007ffeefbff1c0, __p=0x0000000100704da0) at memory:1635:14
        frame #10: 0x000000010000b712 test`jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >::object_storage::destroy(this=0x0000000100704d90) at basic_json.hpp:883:17
        frame #11: 0x000000010000b6b8 test`jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >::object_storage::~object_storage(this=0x0000000100704d90) at basic_json.hpp:855:21
        frame #12: 0x000000010000b5a5 test`jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >::object_storage::~object_storage(this=0x0000000100704d90) at basic_json.hpp:852:13
        frame #13: 0x00000001000046cd test`void jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >::destroy_var<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >::object_storage>(this=0x0000000100704d90) at basic_json.hpp:1929:24
        frame #14: 0x00000001000045d6 test`jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >::Destroy_(this=0x0000000100704d90) at basic_json.hpp:1913:21
        frame #15: 0x0000000100004545 test`jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >::~basic_json(this=0x0000000100704d90) at basic_json.hpp:3126:14
        frame #16: 0x00000001000022c5 test`jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >::~basic_json(this=0x0000000100704d90) at basic_json.hpp:3125:9
        frame #17: 0x000000010004ae6b test`std::__1::default_delete<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >::operator(this=0x0000000100704ea8, __ptr=0x0000000100704d90)(jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >*) const at memory:2368:5
        frame #18: 0x000000010004ae2f test`std::__1::unique_ptr<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::default_delete<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > > >::reset(this=0x0000000100704ea8, __p=0x0000000000000000) at memory:2623:7
        frame #19: 0x000000010004adc9 test`std::__1::unique_ptr<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::default_delete<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > > >::~unique_ptr(this=0x0000000100704ea8) at memory:2577:19
        frame #20: 0x0000000100049945 test`std::__1::unique_ptr<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::default_delete<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > > >::~unique_ptr(this=0x0000000100704ea8) at memory:2577:17
        frame #21: 0x000000010004ad09 test`std::__1::allocator<std::__1::unique_ptr<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::default_delete<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > > > >::destroy(this=0x00007ffeefbff538, __p=0x0000000100704ea8) at memory:1936:64
        frame #22: 0x000000010004acdd test`void std::__1::allocator_traits<std::__1::allocator<std::__1::unique_ptr<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::default_delete<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > > > > >::__destroy<std::__1::unique_ptr<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::default_delete<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > > > >((null)=std::__1::true_type @ 0x00007ffeefbff398, __a=0x00007ffeefbff538, __p=0x0000000100704ea8) at memory:1798:18
        frame #23: 0x000000010004acad test`void std::__1::allocator_traits<std::__1::allocator<std::__1::unique_ptr<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::default_delete<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > > > > >::destroy<std::__1::unique_ptr<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::default_delete<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > > > >(__a=0x00007ffeefbff538, __p=0x0000000100704ea8) at memory:1635:14
        frame #24: 0x000000010008e7eb test`std::__1::__vector_base<std::__1::unique_ptr<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::default_delete<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > > >, std::__1::allocator<std::__1::unique_ptr<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::default_delete<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > > > > >::__destruct_at_end(this=0x00007ffeefbff528, __new_last=0x0000000100704ea0) at vector:426:9
        frame #25: 0x000000010008e77b test`std::__1::__vector_base<std::__1::unique_ptr<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::default_delete<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > > >, std::__1::allocator<std::__1::unique_ptr<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::default_delete<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > > > > >::clear(this=0x00007ffeefbff528) at vector:369:29
        frame #26: 0x000000010008e727 test`std::__1::__vector_base<std::__1::unique_ptr<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::default_delete<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > > >, std::__1::allocator<std::__1::unique_ptr<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::default_delete<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > > > > >::~__vector_base(this=0x00007ffeefbff528) at vector:463:9
        frame #27: 0x000000010008e6f8 test`std::__1::vector<std::__1::unique_ptr<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::default_delete<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > > >, std::__1::allocator<std::__1::unique_ptr<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::default_delete<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > > > > >::~vector(this=0x00007ffeefbff528 size=7) at vector:555:5
        frame #28: 0x000000010008e6c5 test`std::__1::vector<std::__1::unique_ptr<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::default_delete<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > > >, std::__1::allocator<std::__1::unique_ptr<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::default_delete<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > > > > >::~vector(this=0x00007ffeefbff528 size=7) at vector:550:5
        frame #29: 0x000000010008e6a5 test`jsoncons::jmespath::detail::jmespath_evaluator<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > const&>::dynamic_resources::~dynamic_resources(this=0x00007ffeefbff528) at jmespath.hpp:389:15
        frame #30: 0x000000010008d4e5 test`jsoncons::jmespath::detail::jmespath_evaluator<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > const&>::dynamic_resources::~dynamic_resources(this=0x00007ffeefbff528) at jmespath.hpp:389:15
        frame #31: 0x000000010003ca43 test`jsoncons::jmespath::detail::jmespath_evaluator<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > const&>::jmespath_expression::evaluate(this=0x00007ffeefbff5f0, doc=0x00007ffeefbff830, ec=0x00007ffeefbff620) at jmespath.hpp:3371:13
        frame #32: 0x000000010000214c test`jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > jsoncons::jmespath::search<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >(doc=0x00007ffeefbff830, path=0x00007ffeefbff6f8) at jmespath.hpp:5163:28
        frame #33: 0x0000000100001915 test`main at segfault.cpp:32:19
        frame #34: 0x00007fff6a3b8cc9 libdyld.dylib`start + 1
        frame #35: 0x00007fff6a3b8cc9 libdyld.dylib`start + 1
    

    What compiler, architecture, and operating system?

    $ g++ --version
    Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/usr/include/c++/4.2.1
    Apple clang version 12.0.0 (clang-1200.0.32.29)
    Target: x86_64-apple-darwin19.6.0
    Thread model: posix
    InstalledDir: /Library/Developer/CommandLineTools/usr/bin
    

    What jsoncons library version?

    • [ ] Latest release 0.168.0
    • [ ] Other release ______
    • [x] master
  • Question: Is there a way to replace a tag or value?

    Question: Is there a way to replace a tag or value?

    Hello, I was wondering if there was a method to replace a tag or value. I couldn't seem to find one so I am attempting to use std::replace and am concerned about picking the correct tag/value in a large json structure with duplicate names.

    {"store":
    {"book": [
    {"category": "reference",
    "author": "Margaret Weis",
    "title": "Dragonlance Series",
    "price": 31.96}, {"category": "reference",
    "author": "Brent Weeks",
    "title": "Night Angel Trilogy",
    "price": 14.70
    }]}}')

  • Undeclared identifiers

    Undeclared identifiers

    Hi, I want to evaluate jsoncons for my latest project, but as I started using it, I directly faced problems with the latest source from Github. So hopefully it is known and I do not make any stupid mistake :)

    By the way, the last version that compiles for me is the 0.98.2.1. Since 0.98.3 it is not working anymore :(

    See the compile output for more details:

    23:13:56: Running steps for project memo... 23:13:56: Configuration unchanged, skipping qmake step. 23:13:56: Starting: "/usr/bin/make" /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++ -c -pipe -g -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -std=c++11 -stdlib=libc++ -mmacosx-version-min=10.7 -Wall -W -fPIC -I../../memo -I. -I/usr/local/include -I../../devlibs/jsoncons/src -I/usr/local/Cellar/qt5/5.5.1_2/mkspecs/macx-clang -o main.o ../src/main.cpp In file included from ../src/main.cpp:30: In file included from ../src/assetmanager.h:5: In file included from ../../devlibs/jsoncons/src/jsoncons/json.hpp:10: In file included from ../../devlibs/jsoncons/src/jsoncons/json1.hpp:20: In file included from ../../devlibs/jsoncons/src/jsoncons/json_structures.hpp:20: In file included from ../../devlibs/jsoncons/src/jsoncons/jsoncons.hpp:20: In file included from ../../devlibs/jsoncons/src/jsoncons/jsoncons_io.hpp:22: ../../devlibs/jsoncons/src/jsoncons/ovectorstream.hpp:112:46: warning: unused parameter 'mode' [-Wunused-parameter] std::ios_base::openmode mode = std::ios_base::out) override ^ ../../devlibs/jsoncons/src/jsoncons/ovectorstream.hpp:161:60: warning: unused parameter 'mode' [-Wunused-parameter] pos_type seekpos(pos_type pos, std::ios_base::openmode mode ^ ../../devlibs/jsoncons/src/jsoncons/ovectorstream.hpp:200:16: error: use of undeclared identifier 'pptr' return pptr() - pbase(); ^ ../../devlibs/jsoncons/src/jsoncons/ovectorstream.hpp:200:25: error: use of undeclared identifier 'pbase' return pptr() - pbase(); ^ ../../devlibs/jsoncons/src/jsoncons/ovectorstream.hpp:206:9: error: use of undeclared identifier 'pubimbue' pubimbue(loc); ^ ../../devlibs/jsoncons/src/jsoncons/ovectorstream.hpp:211:9: error: use of undeclared identifier 'clear' clear(); ^ ../../devlibs/jsoncons/src/jsoncons/ovectorstream.hpp:212:9: error: use of undeclared identifier 'seekp' seekp(0, std::ios::beg); ^ In file included from ../src/main.cpp:30: In file included from ../src/assetmanager.h:5: In file included from ../../devlibs/jsoncons/src/jsoncons/json.hpp:10: In file included from ../../devlibs/jsoncons/src/jsoncons/json1.hpp:20: ../../devlibs/jsoncons/src/jsoncons/json_structures.hpp:236:44: error: redefinition of 'allocator_type' typedef typename JsonT::allocator_type allocator_type; ^ ../../devlibs/jsoncons/src/jsoncons/json_structures.hpp:234:44: note: previous definition is here typedef typename JsonT::allocator_type allocator_type; ^ In file included from ../src/main.cpp:30: In file included from ../src/assetmanager.h:5: In file included from ../../devlibs/jsoncons/src/jsoncons/json.hpp:10: In file included from ../../devlibs/jsoncons/src/jsoncons/json1.hpp:22: ../../devlibs/jsoncons/src/jsoncons/json_output_handler.hpp:201:31: warning: unused parameter 'name' [-Wunused-parameter] void do_name(const CharT* name, size_t length) override ^ ../../devlibs/jsoncons/src/jsoncons/json_output_handler.hpp:201:44: warning: unused parameter 'length' [-Wunused-parameter] void do_name(const CharT* name, size_t length) override ^ ../../devlibs/jsoncons/src/jsoncons/json_output_handler.hpp:225:47: warning: unused parameter 'length' [-Wunused-parameter] void do_string_value(const CharT_, size_t length) override ^ In file included from ../src/main.cpp:30: In file included from ../src/assetmanager.h:5: In file included from ../../devlibs/jsoncons/src/jsoncons/json.hpp:10: In file included from ../../devlibs/jsoncons/src/jsoncons/json1.hpp:25: In file included from ../../devlibs/jsoncons/src/jsoncons/json_deserializer.hpp:17: ../../devlibs/jsoncons/src/jsoncons/json_input_handler.hpp:241:31: warning: unused parameter 'p' [-Wunused-parameter] void do_name(const CharT_ p, size_t length, const basic_parsing_context&) override ^ ../../devlibs/jsoncons/src/jsoncons/json_input_handler.hpp:241:41: warning: unused parameter 'length' [-Wunused-parameter] void do_name(const CharT* p, size_t length, const basic_parsing_context&) override ^ ../../devlibs/jsoncons/src/jsoncons/json_input_handler.hpp:249:47: warning: unused parameter 'length' [-Wunused-parameter] void do_string_value(const CharT_, size_t length, const basic_parsing_context&) override ^ In file included from ../src/main.cpp:30: In file included from ../src/assetmanager.h:5: In file included from ../../devlibs/jsoncons/src/jsoncons/json.hpp:10: In file included from ../../devlibs/jsoncons/src/jsoncons/json1.hpp:25: ../../devlibs/jsoncons/src/jsoncons/json_deserializer.hpp:114:66: warning: unused parameter 'context' [-Wunused-parameter] void do_begin_object(const basic_parsing_context<char_type>& context) override ^ ../../devlibs/jsoncons/src/jsoncons/json_deserializer.hpp:141:65: warning: unused parameter 'context' [-Wunused-parameter] void do_begin_array(const basic_parsing_context<char_type>& context) override ^ In file included from ../src/main.cpp:30: In file included from ../src/assetmanager.h:5: In file included from ../../devlibs/jsoncons/src/jsoncons/json.hpp:10: In file included from ../../devlibs/jsoncons/src/jsoncons/json1.hpp:26: In file included from ../../devlibs/jsoncons/src/jsoncons/json_reader.hpp:20: ../../devlibs/jsoncons/src/jsoncons/parse_error_handler.hpp:132:69: warning: unused parameter 'context' [-Wunused-parameter] const basic_parsing_context& context) throw (parse_exception) ^ ../../devlibs/jsoncons/src/jsoncons/parse_error_handler.hpp:148:65: warning: unused parameter 'context' [-Wunused-parameter] const basic_parsing_context& context) throw (parse_exception) ^ In file included from ../src/main.cpp:30: In file included from ../src/assetmanager.h:5: In file included from ../../devlibs/jsoncons/src/jsoncons/json.hpp:10: ../../devlibs/jsoncons/src/jsoncons/json1.hpp:39:35: error: use 'template' keyword to treat 'rebind_alloc' as a dependent template name std::allocator_traits::rebind_alloc alloc(allocator); ^ template ../../devlibs/jsoncons/src/jsoncons/json1.hpp:39:47: error: expected ';' after expression std::allocator_traits::rebind_alloc alloc(allocator); ^ ; ../../devlibs/jsoncons/src/jsoncons/json1.hpp:43:18: error: use of undeclared identifier 'alloc' T_ storage = alloc.allocate(1); ^ ../../devlibs/jsoncons/src/jsoncons/json1.hpp:47:39: error: use 'template' keyword to treat 'rebind_traits' as a dependent template name std::allocator_traits::rebind_traits::construct(alloc, storage, allocator); ^ template ../../devlibs/jsoncons/src/jsoncons/json1.hpp:47:67: error: use of undeclared identifier 'alloc' std::allocator_traits::rebind_traits::construct(alloc, storage, allocator); ^ ../../devlibs/jsoncons/src/jsoncons/json1.hpp:54:9: error: use of undeclared identifier 'alloc' alloc.deallocate(storage,1); ^ ../../devlibs/jsoncons/src/jsoncons/json1.hpp:64:35: error: use 'template' keyword to treat 'rebind_alloc' as a dependent template name std::allocator_traits::rebind_alloc alloc(allocator); ^ template ../../devlibs/jsoncons/src/jsoncons/json1.hpp:64:47: error: expected ';' after expression std::allocator_traits::rebind_alloc alloc(allocator); ^ ; ../../devlibs/jsoncons/src/jsoncons/json1.hpp:68:18: error: use of undeclared identifier 'alloc' T* storage = alloc.allocate(1); ^ ../../devlibs/jsoncons/src/jsoncons/json1.hpp:72:39: error: use 'template' keyword to treat 'rebind_traits' as a dependent template name std::allocator_traits::rebind_traits::construct(alloc, storage, std::forward(val), allocator); ^ template ../../devlibs/jsoncons/src/jsoncons/json1.hpp:72:67: error: use of undeclared identifier 'alloc' std::allocator_traits::rebind_traits::construct(alloc, storage, std::forward(val), allocator); ^ ../../devlibs/jsoncons/src/jsoncons/json1.hpp:79:9: error: use of undeclared identifier 'alloc' alloc.deallocate(storage,1); ^ ../../devlibs/jsoncons/src/jsoncons/json1.hpp:89:35: error: use 'template' keyword to treat 'rebind_alloc' as a dependent template name std::allocator_traits::rebind_alloc alloc(allocator); ^ template fatal error: too many errors emitted, stopping now [-ferror-limit=] 12 warnings and 20 errors generated. make: *** [main.o] Error 1 23:13:57: The process "/usr/bin/make" exited with code 2. Error while building/deploying project memo (kit: GameDev) When executing step "Make" 23:13:57: Elapsed time: 00:01.

  • Replace in JSON string

    Replace in JSON string

    Dear Daniel,

    Thank you once again for the product, my team loves it and we are heavily using it on our project.

    We are currently facing a challenge and I would like to ask you for an advice on how to go about it using jsoncons:

    1. We have a JSON string.
    2. We are using JSON path to find a specific item on our JSON.
    3. [HERE is the challenge] - we need to replace in the original string, the found item (string) with another string having the same size without modifying anything else in the original string.

    We want to avoid finding the item and then replacing in the original string using string find and replace because the found item can be a very small string (e.g. "abc") and replacing seamlessly after finding could lead to several false positives.

    Example:

    Considering the following JSON string :

    {"items":[{"id":1,"name":"abc","expiry":"0420"},{"id":2,"name":"id","expiry":"0720"}]}

    and the following JSONPath: $.items[1].name

    I would be retrieving the string "id".

    I would like to substitute the found string "id" with the string "ab" in the original message without modifying anything else about it generating the following:

    {"items":[{"id":1,"name":"abc","expiry":"0420"},{"id":2,"name":"ab","expiry":"0720"}]}

    If I was to seamlessly find and replace in the raw string "id" with "ab" it would lead to the following string:

    {"items":[{"ab":1,"name":"abc","expiry":"0420"},{"ab":2,"name":"ab","expiry":"0720"}]}

    How would you go about this problem? Thank you once again.

  • Writing float results in '.0' written

    Writing float results in '.0' written

    When writing json object into a stream, it writes '.0' instead of actual float.

    Unable to read json from a stream containing '.0' as a field's value (probably this is a correct behavior).

    #include <iostream>
    #include <fstream>
    
    #include "jsoncons/json.hpp"
    
    int main(int argc, char** argv)
    {
            try
            {
                    jsoncons::json out;
                    out["a"] = 1.0;
    
                    std::ofstream of("jsontest.json");
                    of << out << std::endl;
    
                    jsoncons::json in = jsoncons::json::parse_file("jsontest.json");
                    std::cout << in << std::endl;
            }
            catch(const std::exception& e)
            {
                    std::cerr << e.what() << std::endl;
            }
    
            return 0;
    }
    
  • Serialization of maps with non-string key

    Serialization of maps with non-string key

    Hi, I would really like to have an int keyed map working with jsoncons. For this I though about converting the keys on the fly to string an back during serialization and deserialization.

    However, if I try to create such a trait, I get a conflict with already supported maps. See the code and error log below. Is there any way out?

    Thanks.

    namespace jsoncons {
    
        template <class Json, typename T>
        struct json_type_traits<Json,std::map<int, T>> {
    
            static const bool is_assignable = true;
            static bool is(const Json& val) noexcept {
                if (!val.is_object())
                    return false;
    
                return true;
            }
    
            static std::map<int, T> as(const Json& val) {
                std::map<std::string, T> map = val.template as<std::map<std::string, T>>();
    
                std::map<int, T> result(map.size());
                std::transform(std::begin(map), std::end(map),
                       std::begin(result),
                       [](const std::pair<std::string, T>& element) -> std::pair<int, T> {
                          return std::make_pair<int, T>(std::stoi(element.first), element.second);
                        });
    
                return result;
            }
    
            static Json to_json(std::map<int, T> val) {
              std::map<std::string, T> result(val.size());
              std::transform(std::begin(val), std::end(val),
                     std::begin(result),
                     [](const std::pair<int, T>& element) -> std::pair<std::string, T> {
                        return std::make_pair<std::string, T>(std::to_string(element.first), element.second);
                      });
              return Json(result);
            }
        };
    
        namespace detail {
            template<typename T>
            struct is_map_like<std::map<int, T>>: public std::true_type {};
        }
    }
    

    Error log

    include/jsoncons/basic_json.hpp:2940:16: error: ambiguous partial specializations of 'json_type_traits<jsoncons::basic_json<char, jsoncons::preserve_order_policy, std::__1::allocator<char> >,
          std::__1::map<int, int, std::__1::less<int>, std::__1::allocator<std::__1::pair<const int, int> > >, void>'
            : var_(json_type_traits<basic_json,T>::to_json(val).var_)
                   ^
    include/jsoncons/json_container_types.hpp:1511:23: note: in instantiation of function template specialization 'jsoncons::basic_json<char, jsoncons::preserve_order_policy, std::__1::allocator<char>
          >::basic_json<std::__1::map<int, int, std::__1::less<int>, std::__1::allocator<std::__1::pair<const int, int> > > >' requested here
                it->value(Json(std::forward<T>(value)));
                          ^
    include/jsoncons/basic_json.hpp:4150:35: note: in instantiation of function template specialization 'jsoncons::json_object<std::__1::basic_string<char>, jsoncons::basic_json<char,
          jsoncons::preserve_order_policy, std::__1::allocator<char> >, void>::insert_or_assign<std::__1::map<int, int, std::__1::less<int>,
          std::__1::allocator<std::__1::pair<const int, int> > > &, std::__1::allocator<char> >' requested here
                return object_value().insert_or_assign(name, std::forward<T>(val));
                                      ^
    include/jsoncons/basic_json.hpp:2019:45: note: in instantiation of function template specialization 'jsoncons::basic_json<char, jsoncons::preserve_order_policy, std::__1::allocator<char>
          >::insert_or_assign<std::__1::map<int, int, std::__1::less<int>, std::__1::allocator<std::__1::pair<const int, int> > > &>' requested here
                parent_.evaluate_with_default().insert_or_assign(key_, std::forward<T>(val));
                                                ^
    note: in instantiation of function template specialization 'jsoncons::basic_json<char, jsoncons::preserve_order_policy, std::__1::allocator<char>
          >::proxy<jsoncons::basic_json<char, jsoncons::preserve_order_policy, std::__1::allocator<char> > >::operator=<std::__1::map<int, int,
          std::__1::less<int>, std::__1::allocator<std::__1::pair<const int, int> > > &>' requested here
    z["a"] = a;
           ^
    include/jsoncons/json_type_traits.hpp:707:8: note: partial specialization matches [with Json = jsoncons::basic_json<char, jsoncons::preserve_order_policy, std::__1::allocator<char> >, T =
          std::__1::map<int, int, std::__1::less<int>, std::__1::allocator<std::__1::pair<const int, int> > >]
    struct json_type_traits<Json, T, 
           ^
    Utils.h:216:12: note: partial specialization matches [with Json = jsoncons::basic_json<char, jsoncons::preserve_order_policy, std::__1::allocator<char> >, T = int]
        struct json_type_traits<Json,std::map<int, T>> {
    
    
  • Compilation Error: No member named 'assign'

    Compilation Error: No member named 'assign'

    I'm getting the following compilation error: json.hpp:1698:41: No member named 'assign' in 'jsoncons::json_type_traits<jsoncons::basic_json<char, jsoncons::json_traits, std::__1::allocator >, std::__1::__bit_const_reference<std::__1::vector<bool, std::__1::allocator > > >'

    template <class T>
        basic_json(T val)
            : var_(null_type())
        {
            json_type_traits<value_type,T>::assign(*this,val);
        }
    
  • jmespath issue with reusing compiled expressions

    jmespath issue with reusing compiled expressions

    First to all thank you providing an incredible library!

    We use JMESPath implementation quite extensively but recently we had a big higher throughput requirements which forced use to reuse compiled expression. The usual workaround for this bug (which has been around for a while) was to compile expression every time before usage. jsoncons::jmespath::search takes around 3x longer than evaluate on expression

    Describe the bug

    I did a bit more digging, please have a look at the snippet

    
    #include <jsoncons/json.hpp>
    #include <jsoncons_ext/jmespath/jmespath.hpp>
    
    int main(int argc, char *argv[]) {
      using namespace jsoncons; // for convenience
    
      std::string jtext = R"(
                {
                  "people": [
                    {
                      "age": 20,
                      "other": "foo",
                      "name": "Bob"
                    },
                    {
                      "age": 25,
                      "other": "bar",
                      "name": "Fred"
                    },
                    {
                      "age": 30,
                      "other": "baz",
                      "name": "George"
                    }
                  ]
                }
            )";
    
      auto expr = jmespath::jmespath_expression<json>::compile("sum(people[].age)");
    
      json doc = json::parse(jtext);
    
      json result = expr.evaluate(doc);
      std::cout << pretty_print(result) << "\n\n";
    }
    

    It will result in exception Function called with wrong number of arguments or just outright SIGSEGV but this problem will never occur when using jsoncons::jmespath::search. This seem not to happen with every expression. We seem to have issues with functions like max or sum i.e max([].my_object.sub_field)

    But now if we re-arrange to first ::parse and then ::compile everything is OK and I get result 75.0

    json doc = json::parse(jtext);
    auto expr = jmespath::jmespath_expression<json>::compile("sum(people[].age)");
    

    It looks to me like ::parse breaks a global state that compile introduces

    What compiler, architecture, and operating system?

    • Compiler: gcc 9.2 / gcc 10.2
    • Architecture (e.g. x86, x64) x64
    • Operating system: linux

    What jsoncons library version? release v0.162.2, however this problem has been reoccurring for all previous versions

  • Functional style parsing for custom data members

    Functional style parsing for custom data members

    Using the MACRO style would be nice if we could provide a custom lambda/method/fucntion pointer defining the serialization/deserialization for a class member on a class body. A good example of usage would be for serialization and deserialization of DateTime formats.

    For example let's suppose I want the following type to be JSON serializable/deserializable:

    class Booking {
      public:
        std::string getName();
        DateTime getDate();
      private:
        std::string _name;
        DateTime _date;
    }
    

    Let's suppose that the custom DateTime structure can be easily converted/represented by a std::string it would be very convenient to use the jsoncons macros to bind converters from and to string. E.g.: Let's assume I have those two methods defined somewhere:

    DataTime fromStringToDataTime(const std::string& str);
    std::string fromDataTimeToString(const DataTime& dataTime);
    

    I would like to be able to use one of the MACROS like the following snippet :

    JSONCONS_ALL_FUNCTION_PARSER_TRAITS(Booking, 
      (getName, "name"),
      (getDate, fromStringToDataTime, fromDataTimeToString, "date")
    )
    

    More generally would be nice if the parameters could accept also lambdas:

    JSONCONS_ALL_FUNCTION_PARSER_TRAITS(Booking, 
      (getName, "name"),
      (getDate, [](const std::string& str) { return Dat3Time(); }, [](const DateTime& date){ return std::string();}, "date")
    )
    

    It seems ambitious and I don't know the perks of the implementation but as user it would greatly benefit us.

    More generally the functions / lambdas to be provided are constrained in a way that:

    1. the first one should provide a conversion from a data-structure which jsoncons knows how to serialize/deserialize (even custom ones with other macros defined)
    2. the second one converts from the unkown type to the known data type in point 1.

    As another example let's say I want to deserialize the following json:

    {
      "company": "CompanySA",
      "resources": [
        {
          "employee_name": "Rod",
          "employee_surname": "Bro"
        },
        {
          "employee_name": "Ale",
          "employee_surname": "Dha"     
        }
      ]
    }
    

    into the following data structure:

    class Company {
      public:
        std::string getName();
       const std::vector<uint64_t> getIds();
      private:
        std::string _name;
        std::vector<uint64_t> _employeeIds;
    }
    

    and let's say that JSONCONS knows how to deserialize/deserialize the following data structure (proper MACRO provided in order to tell jsoncons how to do it):

    class Employee {
      public:
        std::string getName();
        DateTime getSurname();
      private:
        std::string _name;
        std::string _surname;
    }
    
    JSONCONS_ALL_CTOR_GETTER_NAME_TRAITS(Employee,
                                          (getName, "employee_name"),
                                          (getSurname, "employee_surname")
                                         )
    

    Let's say that I have two internal functions that are able to map between std::vector<Employee> and std::vector<uint64_t> like:

    std::vector<Employee> fromIdsToEmployees(const std::vector<uint64_t>& ids);
    std::vector<uint64_t> fromEmployeesToIds(const std::vector<Employee>& ids);
    

    I would like to provide the following macro to deserialize from the initial json:

    JSONCONS_ALL_FUNCTION_PARSER_TRAITS(Company, 
      (getName, "company"),
      (getIds, fromEmployeesToIds,  fromIdsToEmployees, "resources")
    )
    

    Another huge value for that is that it would provide the ability for users to include Data types of third part libraries into the class members, the user only need to 'translate' from/to json in a functional way... (hope it's clear :) )

    So even if my code was not the one to define DateTime datastructure I could define the feasible conversion from and to it. (If there is already something similar I would be very interested to know)

  • JSON path issue with custom allocator

    JSON path issue with custom allocator

    Describe the bug Using jsoncons with custom alloctor is supported. For example you can parse JSON using custom allocator: see for example: sample_allocators.hpp

    template<typename T> my_allocator {
    // Interface is the same as std::allocator
    };
    
    // then:
     using my_json = basic_json<char, sorted_policy, my_allocator<char>>;
     json_decoder<my_json, my_allocator<char>> decoder(result_allocator_arg, my_allocator<char>{},
                                                                   my_allocator<char>{});
    basic_json_reader<char, string_source<char>, my_allocator<char>> reader(input, decoder, my_allocator<char>{});
    reader.read();
    
     my_json j = decoder.get_result();
     std::cout << pretty_print(j) << "\n";
    

    This code would compile and run as expected. The problem will start when I want use this with json path:

    std::string_view p{"$.store.book[?(@.price < 10)].author"};
     auto expr = jsoncons::jsonpath::make_expression<my_json>(p);   // this will not compile
     auto r = expr.evaluate(j);
    

    I'm getting an error that:

    /include/jsoncons_ext/jsonpath/jsonpath_selector.hpp:156:75: note:   no known conversion for argument 3 from ‘const key_type’ {aka ‘const std::__cxx11::basic_string<char, std::char_traits<char>, my_allocator<char> >’} to ‘const string_type&’ {aka ‘const std::__cxx11::basic_string<char>&’}
      156 |                                                        const string_type& identifier,
          |                                                        ~~~~~~~~~~~~~~~~~~~^~~~~~~~~
    

    This issue is critical since my use case require that use of custom alloctor that do not use the global heap and require the use of both JSON and JSONPATH.

    Expecting: Being able to compile both JSON and JSONPATH using custom alloctors. It would be even nicer to use the new C++17 polymorphic memory resource.

    See above - code fail to compile. Enumerate the steps to reproduce the bug You can add the code example above to the file json_reader_examples.cpp line 150. Note that I failed to build this example as well (there is an issue with FreelistAllocator alloctor missing default constructor). Include a small, self-contained example if possible See above for the problem description. Please note that I found the location at the code at which the issue was triggered by, I can PR it, or if you prefer I can send it add it to this issue. What compiler, architecture, and operating system?

    • Compiler: g++ (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0
    • Architecture x86, x64)
    • Operating system: Ubuntu 22.04
    • build flags: -Wall -Wextra -g -std=c++17

    What jsoncons library version? Latest from github (commit c369979d8cf12c82b643fc71d5261b3d28f7d4d1).

    • [ ] Latest release 0.169.0
    • [ ] Other release ______
    • [x] master
  • `std::from_chars` parsing fails tests on Windows

    `std::from_chars` parsing fails tests on Windows

    Describe the bug

    Recently, jsoncons has started using std::from_char when available. We are on Windows, with _MSC_VER == 1934, which does enable it based on the checks in compiler_support.hpp. However, std::from_chars seems unable to parse all floating point representations, as demonstrated by tests failing (e.g., "csv_parser number detection" fails).

    I don't know if this is a quirk of the MSVC implementation that affects all versions, or if it is specific to our version of MSVC. But at present the std::from_char parsing does not have feature-parity with the classic strtof/strtod.

    Enumerate the steps to reproduce the bug

    • Clone jsoncons
    • Build with MSVC (I used VS 17.4.1, _MSC_VER == 1934)
    • Run tests

    Include a small, self-contained example if possible

    #include <charconv>
    #include <string>
    #include <iostream>
    
    int main() {
        const std::string s = "5001173100E95978";
        double d = 0.0;
        auto res = std::from_chars(s.data(), s.data() + s.size(), d);
        if (res.ec != std::errc())
        {
            std::cout << "from_chars: convert chars to double failed" << std::endl;
        }
        else
        {
            std::cout << "from_chars: " << d << std::endl;
        }
    
        char* ptr = nullptr;
        d = std::strtod(s.data(), &ptr);
        if (ptr == s.data())
        {
            std::cout << "strtod: convert chars to double failed" << std::endl;
        }
        else
        {
            std::cout << "strtod: " << d << std::endl;
        }
    
        return 0;
    }
    

    This code demonstrates the inconsistency. Outputs:

    GCC 12.2 (compiler explorer)

    from_chars: convert chars to double failed
    strtod: inf
    

    MSVC 19.33 (compiler explorer)

    from_chars: convert chars to double failed
    strtod: inf
    

    What compiler, architecture, and operating system?

    • Compiler: MSVC 17.4.1, _MSC_VER == 1934
    • Architecture (e.g. x86, x64) x64
    • Operating system: Windows 10

    What jsoncons library version?

    • [ ] Latest release 0.169.0
    • [ ] Other release ______
    • [x] master
  • Current build fails with MinGW 11.2 because it doesn't have std::from_chars()

    Current build fails with MinGW 11.2 because it doesn't have std::from_chars()

    Out build fails with gcc on windows (MinGW) because it doesn't find the std::from_chars() function.

    parse_number.hpp:948:41: error: no matching function for call to 'from_chars(char*, char*, double&)'
    const auto res = std::from_chars(input.data(), input.data() + len, val);
    

    in compiler_support.hpp there is already a detection of the feature, but this doesn't work for MinGW (GCC 11.2.0)

    #if !defined(JSONCONS_HAS_STD_FROM_CHARS)
    #  if defined(__GNUC__)
    #   if (__GNUC__ >= 11)
    #    if (__cplusplus >= 201703)
    #     define JSONCONS_HAS_STD_FROM_CHARS 1
    #    endif // (__cplusplus >= 201703)
    #   endif // (__GNUC__ >= 11)
    #  endif // defined(__GNUC__)
    #  if defined(_MSC_VER)
    #   if (_MSC_VER >= 1924 && _MSVC_LANG >= 201703)
    #    define JSONCONS_HAS_STD_FROM_CHARS 1
    #   endif // (_MSC_VER >= 1924 && MSVC_LANG >= 201703)
    #  endif // defined(_MSC_VER)
    #endif
    #if defined(JSONCONS_HAS_STD_FROM_CHARS)
    #include <charconv>
    #endif
    

    To make this work for MinGW (skip the std::from_chars)

    #if !defined(JSONCONS_HAS_STD_FROM_CHARS)
    #  if defined(__GNUC__)
    #   if (__GNUC__ >= 11)
    #    if (__cplusplus >= 201703)
    #     if !defined(__MINGW32__)
    #      define JSONCONS_HAS_STD_FROM_CHARS 1
    #     endif // !defined(__MINGW32__)
    #    endif // (__cplusplus >= 201703)
    #   endif // (__GNUC__ >= 11)
    #  endif // defined(__GNUC__)
    #  if defined(_MSC_VER)
    #   if (_MSC_VER >= 1924 && _MSVC_LANG >= 201703)
    #    define JSONCONS_HAS_STD_FROM_CHARS 1
    #   endif // (_MSC_VER >= 1924 && MSVC_LANG >= 201703)
    #  endif // defined(_MSC_VER)
    #endif
    #if defined(JSONCONS_HAS_STD_FROM_CHARS)
    #include <charconv>
    #endif
    

    What compiler, architecture, and operating system?

    • Compiler: GCC 11.2.0 (MinGW)
    • Architecture: x64
    • Operating system: Windows 10/11 64-Bit

    What jsoncons library version?

    • [ ] Latest release 0.169.0
    • [ ] Other release ______
    • [X] master
  • Temporary allocations from std::stable_sort even when using ojson

    Temporary allocations from std::stable_sort even when using ojson

    Thanks four providing this library!

    I am trying to use it because of its memory-efficient streaming capabilities for very large JSON files.

    However, the parsing performance seems slow to me. It takes ~60s for 2.5 GiB, so ~60 MB/s. That seems slow when hearing of (untested) multiple GB/s for simdjson. Even gzip decompression is many times faster (> 200 MB/s).

    I tried to look a bit into performance bottlenecks and most of the time is spent almost equally much in basic_json_parser::parse_some, basic_json_parser::parse_string, and jsoncons::unicode_traits::is_legal_utf8. Nothing I can do much about. I also did take a look with heaptrack and was surprised to see millions of temporary allocations from inside std::stable_sort from inside jsoncons::json.

    Ok, so I found it sorts keys alphabetically. I find this a questionable default because it sacrifices performance for something I don't need but it's fine as long as there is an alternative. Next, I tried jsoncons::ojson, which is said to preserve the original order, thinking that this should get rid of the problematic std::stable_sort.

    But jsoncons::ojson also calls std::stable_sort unexpectedly.

    I tried to copy-paste the code of order_preserving_json_object and order_preserving_policy into a patched_jsoncons namespace and replaced the std::stable_sort inside order_preserving_json_object::build_index with std::sort and voila, the millions temporary allocations from std::stable_sort are gone. I'm still seeing millions of temporary allocations inside build_index for the _index.reserve call though. I'm not sure why it is flagged as temporary. The runtime improvements for a 2.5 GiB chrome trace JSON file are unfortunately not significant but those allocations still seem wasteful.

    Now, I'm not 100% sure why std::stable_sort is used. It seems unnecessary to me. It has to be sorted somehow because std::unique is called at some point. (Sorting inside build_index and then calling std::unique outside assuming that build_index did sort seems hard to read to me. I think the sort and call to std::unique should be right next to each other.)

    What compiler, architecture, and operating system?

    • Compiler: Clang 14
    • Architecture (e.g. x86, x64) x64
    • Operating system: Ubuntu 22.04

    What jsoncons library version?

    • [x] Latest release 0.168.7
  • Support JSON Schema Draft 2020-12

    Support JSON Schema Draft 2020-12

    The current version of JSON Schema is Draft 2020-12, whereas jsoncons currently supports Draft 7, which is two versions behind.

    It would be great if jsoncons supported Draft 2020-12!

    It would of course be useful also to retain the Draft 7 support, to allow validation against schemas written to conform to either draft.

    I haven't looked to see how great the changes are (and so how big a feature request this is!)

  • Access the repo via SVN does not work

    Access the repo via SVN does not work

    Accessing the GITHUB repo via SVN does not work

    For reasons out of my control I need to access Github repost via SVN instead of GIT. Please be patient with me. :-)

    But: When trying to checkout the repo on Windows via: svn.exe co https://github.com/danielaparker/jsoncons.git/trunk

    ...one receives these errors: svn: E175002: Unexpected HTTP status 504 'Gateway Timeout' on '/danielaparker/jsoncons.git/!svn/bc/25631' svn: E175002: Unexpected HTTP status 504 'Gateway Timeout' on '/danielaparker/jsoncons.git/trunk'

    With several other repos I tried to cross-check its working just fine. So I assume its not a network issue nor a SVN tool incompatibility. Any chance to look into?

convert json/xml/bson to c++ struct

xpack 用于在C++结构体和json/xml之间互相转换, bson在xbson中支持。 只需要头文件, 无需编译库文件。 具体可以参考example的例子 基本用法 容器支持 FLAG 别名 位域 继承 枚举 自定义编解码 char数组 第三方类和结构体 格式化缩进 XML数组 Qt支持 重要

Jan 6, 2023
A small header-only library for converting data between json representation and c++ structs

Table of Contents Table of Contents What Is json_dto? What's new? v.0.3.0 v.0.2.14 v.0.2.13 v.0.2.12 v.0.2.11 v.0.2.10 v.0.2.9 v.0.2.8 v.0.2.7 v.0.2.6

Dec 27, 2022
https://github.com/json-c/json-c is the official code repository for json-c. See the wiki for release tarballs for download. API docs at http://json-c.github.io/json-c/

\mainpage json-c Overview and Build Status Building on Unix Prerequisites Build commands CMake options Testing Building with vcpkg Linking to libjson-

Dec 31, 2022
json_struct is a single header only C++ library for parsing JSON directly to C++ structs and vice versa

Structurize your JSON json_struct is a single header only library that parses JSON to C++ structs/classes and serializing structs/classes to JSON. It

Dec 28, 2022
A very sane (header only) C++14 JSON library

JeayeSON - a very sane C++14 JSON library JeayeSON was designed out of frustration that there aren't many template-based approaches to handling JSON i

Nov 28, 2022
C++ header-only JSON library
C++ header-only JSON library

Welcome to taoJSON taoJSON is a C++ header-only JSON library that provides a generic Value Class, uses Type Traits to interoperate with C++ types, use

Dec 27, 2022
A small header-only json library in C.

xjson A small header-only json library for C. The "unique" feature is that it allows use of the same code to serialize as well as deserialize, greatly

Jul 19, 2022
a header-file-only, JSON parser serializer in C++

PicoJSON - a C++ JSON parser / serializer Copyright © 2009-2010 Cybozu Labs, Inc. Copyright © 2011-2015 Kazuho Oku Licensed under 2-clause BSD license

Dec 27, 2022
A C++17 single-file header-only library to wrap RapidJSON SAX interface

A C++17 single-file header-only library for RapidJSON SAX interface

Nov 4, 2022
Lightweight, header-only, C++17 configuration library

uconfig C++ header-only library to parse and emit multi-format configuration for your app. For example, you can parse JSON-file into the config and th

Dec 2, 2022
JSON parser and generator for C/C++ with scanf/printf like interface. Targeting embedded systems.

JSON parser and emitter for C/C++ Features ISO C and ISO C++ compliant portable code Very small footprint No dependencies json_scanf() scans a string

Dec 30, 2022
C library for encoding, decoding and manipulating JSON data

Jansson README Jansson is a C library for encoding, decoding and manipulating JSON data. Its main features and design principles are: Simple and intui

Dec 31, 2022
This is a JSON C++ library. It can write and read JSON files with ease and speed.

Json Box JSON (JavaScript Object Notation) is a lightweight data-interchange format. Json Box is a C++ library used to read and write JSON with ease a

Dec 4, 2022
QJson is a qt-based library that maps JSON data to QVariant objects.

QJson JSON (JavaScript Object Notation) is a lightweight data-interchange format. It can represents integer, real number, string, an ordered sequence

Dec 2, 2022
🗄️ single header json parser for C and C++

??️ json.h A simple single header solution to parsing JSON in C and C++. JSON is parsed into a read-only, single allocation buffer. The current suppor

Jan 7, 2023
single-header json parser for c99 and c++

ghh_json.h a single-header ISO-C99 (and C++ compatible) json loader. why? obviously this isn't the first json library written for C, so why would I wr

Dec 1, 2022
A simple class for parsing JSON data into a QVariant hierarchy and vice versa.

The qt-json project is a simple collection of functions for parsing and serializing JSON data to and from QVariant hierarchies. NOTE: Qt5 introduced a

Dec 13, 2022
A simple class for parsing JSON data into a QVariant hierarchy and vice versa.

The qt-json project is a simple collection of functions for parsing and serializing JSON data to and from QVariant hierarchies. NOTE: Qt5 introduced a

Dec 13, 2022
A generator of JSON parser & serializer C++ code from structure header files

JSON-CPP-gen This is a program that parses C++ structures from a header file and automatically generates C++ code capable of serializing said structur

Oct 13, 2022