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

Overview

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?

    opened by rohitjoshi 33
  • 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.

    opened by andysCaplin 19
  • 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
    Bug Resolved 
    opened by mtmorgan 17
  • 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
    }]}}')

    Question 
    opened by WorksWellWithOthers 15
  • 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.

    opened by HerrBvomSee 15
  • 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.

    Question Enhancement 
    opened by rbroggi 14
  • 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;
    }
    
    Bug Resolved 
    opened by rychale 13
  • 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>> {
    
    
    Enhancement 
    opened by patternoia 12
  • 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);
        }
    
    opened by stephenberry 12
  • 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

    Bug Resolved 
    opened by siemib 11
  • 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)

    Feature request 
    opened by rbroggi 11
  • 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
    Bug 
    opened by boazsade 2
  • `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
    Bug 
    opened by cschreib-ibex 2
  • 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
    Bug 
    opened by JohannAnhofer 1
  • 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
    Bug 
    opened by mxmlnkn 5
  • 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!)

    Feature request 
    opened by oiwg 1
  • 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?

    Bug 
    opened by MortenMacFly 2
Releases(v0.169.0)
  • v0.169.0(Nov 2, 2022)

    Defect fixes:

    Performance Enhancement:

    • Use std::from_chars for chars to double conversion when supported in GCC and VC.

    Enhancements:

    • Added a size() accessor function to basic_staj_event. If the event type is a key or a string_value or a byte_string_value, returns the size of the key or string or byte string value. If the event type is a begin_object or a begin_array, returns the size of the object or array if known, otherwise 0. For all other event types, returns 0.

    • Extended the parsers/cursors/encoder for JSON, CBOR, Msgpack, BSON, CSV, UBJSON so that they are resettable to new sources/sinks, contributed by ecorm

    Changes:

    • For consistency with library naming conventions, the directory include/jsoncons/json_merge_patch has been renamed to include/jsoncons/mergepatch, the namespace json_merge_patch to mergepatch, and the include file json_merge_patch.hpp to mergepatch.hpp.
    Source code(tar.gz)
    Source code(zip)
  • v0.168.7(May 20, 2022)

    Defect fixes:

    Source code(tar.gz)
    Source code(zip)
  • 0.168.6(May 13, 2022)

    Bug Fix:

    • Fixed an issue with the order preserving ojson erase function that takes two iterator arguments.

    Enhancement:

    • The basic_json::erase function return value, previously void, is now an iterator following the last removed element,
    array_iterator erase(const_array_iterator pos);
    object_iterator erase(const_object_iterator pos);
    
    array_iterator erase(const_array_iterator first, const_array_iterator last);
    object_iterator erase(const_object_iterator first, const_object_iterator last);
    

    See Issue #363

    Source code(tar.gz)
    Source code(zip)
  • 0.168.5(Mar 23, 2022)

  • v0.168.4(Mar 8, 2022)

    Issues fixed:

    • Fixed issue #352 regarding json_type_traits macro failure when number of parameters reached 47.

    Enhancement:

    Increased maximum number of parameters in json_type_traits macros from 50 to 70.

    Source code(tar.gz)
    Source code(zip)
  • v0.168.3(Jan 23, 2022)

  • v0.168.2(Jan 3, 2022)

  • v0.168.1(Oct 24, 2021)

  • v0.168.0(Sep 27, 2021)

    Bugs fixed:

    • Fixed issue #335. The 0b... notation used in a cbor header file has been replaced with 0x... notation. The 0b... notation used is only standard compliant with C++14 and later, although supported in some C++ 11 compilers.

    • Fixed issue with csv automatic number detection discovered while investigating issue #333.

    Enhancements to jsonpointer extension:

    • Support construction of a json_pointer from a URI fragment representation of a JSON Pointer.

    • Support stringifying a json_pointer to a URI fragment representation with the to_uri_fragment function.

    Source code(tar.gz)
    Source code(zip)
  • v0.167.1(Aug 13, 2021)

  • v0.167.0(Aug 6, 2021)

    Bugs fixed:

    • Fixed issue with a json_cursor hanging if opened with an empty file or string, detected by google/OSS-fuzz.

    • Fixed issue with the unary minus in a JSONPath filter expression, where an expression such as $[[email protected] > -42] would fail to parse.

    • Fixed issue with private typedef and Intel C++ Compiler via PR #327

    Changes:

    • In the csv extension, the enum name mapping_kind has been renamed to csv_mapping_kind, and the csv_options.mapping function has been renamed to csv_options.mapping_kind. The old names have been deprecated but are still usable.

    Enhancements:

    • Added support for JSON Merge Patch.

    • Added support in JSONPath expressions for '%' (modulus) operator

    Source code(tar.gz)
    Source code(zip)
  • v0.166.0(Jul 6, 2021)

    jsonpath bugs fixed:

    • Fixed issue with normalized paths produced by JSONPath expressions with filters

    jsonpath enhancements:

    • Added support for a parent selector, using the `^' symbol, following jsonpath-plus.

    • Implemented a number of performance optimizations.

    jsonschema enhancements:

    • Improved error messages reported when compiling a schema document

    • Added a check that the "$schema" keyword, if present, is Draft 7.

    Source code(tar.gz)
    Source code(zip)
  • v0.165.0(Jun 5, 2021)

    Enhancements for bson extension:

    • Added semantic tags float128, id, regex, and code to support bson decode and encode for decimal128, ObjectId, regex, and Javascript code.

    • Support has been added for ObjectId, regex, decimal128 and the other non-deprecated bson types, as requested in issue #321.

    • Parsing now checks that the the number of bytes read for a document, embedded document and array matches the expected total.

    Source code(tar.gz)
    Source code(zip)
  • v0.164.0(May 28, 2021)

    Changes to jsonpath:

    • The values in the result_options bitmask have been changed from

      enum class result_options {value=1, path=2, nodups=4|path, sort=8|path}; (until 0.164.0)

    to

    enum class result_options {value=0, nodups=1, sort=2, path=4};            (since 0.164.0)
    

    In practice this means that any combination of these values that includes result_options::value has the same meaning as before, except that result_options::value can now be omitted. And any combination that includes result_options::path but not result_options::value has the same meaning as before.

    Enhancements to jsonpath:

    • Functions now allow expressions to be passed as arguments, e.g.

      $.books[?(ceil(@.price*100) == 2272)]

    • User provided custom functions are now supported

    Changes to json_reader and csv_reader:

    • The typedefs json_reader and wjson_reader have been deprecated, but for backwards compatibility they are still supported. They have been replaced by json_string_reader and wjson_string_reader for string sources, and json_stream_reader and wjson_stream_reader, for stream sources.

    • The typedefs csv_reader and wcsv_reader have been deprecated, but for backwards compatibility they are still supported. They have been replaced by csv_string_reader and wcsv_string_reader for string sources, and csv_stream_reader and wcsv_stream_reader, for stream sources.

    Source code(tar.gz)
    Source code(zip)
  • v0.163.3(Apr 23, 2021)

    Bugs fixed:

    • Fixed a jsonpath issue where the two overloads of json_query and json_replace that took a callback function argument used a deprecated typedef in an SFINAE condition.
    Source code(tar.gz)
    Source code(zip)
  • v0.163.2(Apr 9, 2021)

  • v0.163.1(Apr 7, 2021)

    Bugs fixed:

    • Reversed change made in 0.163.0 to removal of duplicates with the result_options::nodups, reverting to previous behaviour (only consider as duplicates nodes with the exact same path starting from the root.) That seems to be the consensus.

    • Fixed a memory leak in jsoncons::jsonpath::node_set, see #314, also related, #316

    • Fixed some gcc warnings about non-virtual destructors in the jsonpath, jmespath, and jsonschema extensions by making the destructors protected, see #313. Added the gcc compiler flag -Wnon-virtual-dtor for gcc in the tests/CMakeLists.txt file.

    Source code(tar.gz)
    Source code(zip)
  • v0.163.0(Mar 20, 2021)

    Bugs fixed:

    • Fixed a jsonpath issue with removal of duplicates with the result_options::nodups flag in the case of a union with different paths
    Source code(tar.gz)
    Source code(zip)
  • v0.162.3(Mar 20, 2021)

  • v0.162.2(Mar 13, 2021)

  • v0.162.1(Feb 20, 2021)

  • v0.162.0(Feb 15, 2021)

    Enhancements to jsonpointer

    • The jsonpointer functions get, add, add_if_absent, and replace have an additonal overload with a create_if_missing parameter. If passed true, creates key-object pairs when object keys are missing.

    Enhancements to jsonpath

    • Improved syntax checking for JSONPath unions
    • Simplified function signatures for make_expression, json_query, and json_replace.

    Changes:

    • The jsonpointer function insert has been deprecated and renamed to add_if_absent, for consistency with the other names.
    Source code(tar.gz)
    Source code(zip)
  • v0.161.0(Feb 8, 2021)

    The jsoncons::jsonpath extension has been rewritten, see JSONPath extension revisited.

    Enhancements to JSONPath extension

    • Added a new function make_expression for creating a compiled JSONPath expression for later evaluation.
    • The json_query and json_replace functions now take an optional result_options parameter that allows duplicate values (i.e. values with the same node paths) to be excluded from results, and for results to be sorted in path order.

    Changes to json_query

    • The parameter result_type has been replaced by a bitmask type result_options. For backwards compatability, result_type has been typedefed to result_options, and the value and path enumerators are still there. In addition, result_options provides options for excluding duplicates from results, and for results to be sorted in path order.

    • Until 0.161.0, json_query was limited to returning an array of results, a copy. With 0.161, json_query allows the user to provide a binary callback that is passed two arguments - the path of the item and a const reference to the original item.

    • Until 0.161.0, json_replace allowed the user to provide a unary callback to replace an item in the original JSON with a returned value. This overload is still there, but has been deprecated. With 0.161, json_replace allows the user to provide a binary callback that is passed two arguments - the path of the item and a mutable reference to the original item.

    Changes to supported JSONPath syntax

    • Previous versions allowed optionally omitting the '$' representing the root of the JSON instance in path selectors. This is no longer allowed. In 0.161.0, all path selectors must start with either '$', if relative to the root of the JSON instance, or '@', if relative to the current node. E.g. store.book.0 is not allowed, rather, $store.book.0.
    • Previous versions supported union of completely separate paths, e.g. $..[name.first,address.city]. 0.161.0 does too, but requires that the relative paths name.first and address.city start with a '@', so the example becomes $..[@.name.first,@.address.city] .
    • Previous versions supported unquoted names with the square bracket notation, this is no longer allowed. E.g. $[books] is not allowed, rather $['books'] or $["books"].
    • Previous versions allowed an empty string to be passed as a path argument to json_query. This is no longer allowed, a syntax error will be raised.
    • In 0.161.0, unquoted names in the dot notation are restricted to digits 0-9, letters A-Z and a-z, the underscore character _, and unicode coded characters that are non-ascii. All others names must be enclosed with single or double quotes. In particular, names with hypens (-) must be enclosed with single or double quotes.

    Enhancements to JMESPath extension

    • Function arity errors are now raised during compilation of the JMESPath expression rather than during evaluation.
    Source code(tar.gz)
    Source code(zip)
  • v0.160.0(Jan 19, 2021)

    Bugs fixed:

    • A C++20 change caused a basic_json overloaded operator '==' to be ambiguous despite there being a unique best viable function. Fixed.

    • When parsing MessagePack buffers, lengths were being incorrectly parsed as signed integers. Fixed.

    Enhancements:

    • Added jsonschema extension that implements the JSON Schema Draft 7 specification for validating input JSON, #280

    Changes:

    • Until 0.160.0, jsonpointer::flatten, when applied to an an empty array or empty object, would produce a flattened value of null rather than [] or {}. Since 0.160.0, it will produce [] or {}. For example, given {"bar":{},"foo":[]}, the flattened output was {"/bar":null,"/foo":null}, but is now {"/bar":{},"/foo":[]}. jsonpointer::unflatten will now return the original object.

    Deprecated function removed:

    • The long deprecated basic_json function to_string(const basic_json_encode_options<char_type>&, char_allocator_type&) const has been removed (replacement is dump).
    Source code(tar.gz)
    Source code(zip)
  • v0.159.0(Nov 21, 2020)

    Bugs fixed:

    • Fixed clang 11 compile issues #284 and #285.

    Changes:

    • In the jsonpointer extension, the type names json_ptr and wjson_ptr have been deprecated and renamed to json_pointer and wjson_pointer.

    Enhancements:

    • The json_pointer operators /= and / now support integers.

    • New override for jsonpath::json_replace that searches for all values that match a JSONPath expression and replaces them with the result of a given function, see #279

    • New factory function jmespath::make_expression to create compiled JMESPath expressions.

    Source code(tar.gz)
    Source code(zip)
  • v0.158.0(Oct 8, 2020)

    Bugs fixed:

    • Fixed compilation error with gcc 11, #276 (thanks to Laurent Stacul)

    Changes:

    • In 0.157.0, the _NAME_ convenience macros were augmented to allow an optional mode parameter (JSONCONS_RDWR or JSONCONS_RDONLY) and three optional function object parameters, match (value matches expected), from (convert from type known to jsoncons) and into (convert into type known to jsoncons). In this release - 0.158.0 - the order of the from and into function object parameters has been reversed. If you've provided from and into function objects as arguments in your json traits convenience macros, you'll need to reverse their order, or if you've provided just a from function argument, you'll need to precede it with jsoncons::identity() (or std::identity() if C++20). For the rationale for this change, see #277

    • Conversion errors during decode are now reported more consistently as jsoncons::convert_error, parsing errors remain jsoncons::ser_error (or std::error_code) as before.

    Source code(tar.gz)
    Source code(zip)
  • v0.157.2(Oct 1, 2020)

    Warnings fixed:

    • Fixed C20 deprecated move_iterator access with arrow operator.
    • Fixed PVS-Studio warnings

    OSS-Fuzz issues fixed:

    • Fixed OSS-Fuzz failed throw issue 25891 affecting decode_ubjson and potentially other decode functions. This means that decode functions will throw a ser_error instead of an assertion_error in the presence of certain kinds of bad data.
    Source code(tar.gz)
    Source code(zip)
  • v0.157.1(Sep 26, 2020)

    Bugs fixed:

    • The macros JSONCONS_ALL_MEMBER_NAME_TRAITS and JSONCONS_N_MEMBER_NAME_TRAITS failed at compile time when provided with exactly two optional member arguments, JSONCONS_RDWR followed by a Match function object (other cases were fine.) This has been fixed.

    Change reverted:

    • The name change ser_error to codec_error introduced in 0.157.0 has been reverted back to ser_error. Just in case anybody used it, the name codec_error has been typedefed to ser_error.
    Source code(tar.gz)
    Source code(zip)
  • v0.157.0(Sep 24, 2020)

    Changes:

    • The name ser_error has been deprecated and renamed to codec_error.

    Enhancements:

    • The _NAME_ convenience macros now allow an optional mode parameter (JSONCONS_RDWR or JSONCONS_RDONLY) and three function objects, match (value matches expected), from (convert from type known to jsoncons) and into (convert into type known to jsoncons), #267
    Source code(tar.gz)
    Source code(zip)
  • v0.156.1(Sep 17, 2020)

    Bugs fixed:

    • Fixed issue with jsonpath exception raised when querying empty string, #270

    • Included pull request #273 that fixes an issue with a misnamed macro (BOOST_HAS_FLOAT128 instead of JSONCONS_HAS_FLOAT128) introduced in 0.156.0.

    Source code(tar.gz)
    Source code(zip)
convert json/xml/bson to c++ struct

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

null 450 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

Stiffstream 101 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-

json-c 2.6k 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

Jørgen Lind 275 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

Jeaye Wilkerson 128 Nov 28, 2022
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

The Art of C++ 499 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

Stefan Bachmann 23 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

Kazuho Oku 1k 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

null 5 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

Tinkoff.ru 15 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

Cesanta Software 637 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

Petri Lehtinen 2.7k 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

Anhero inc. 110 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

Flavio Castelli 273 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

Neil Henning 544 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

garrison hinson-hasty 14 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

null 305 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

null 305 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

Viktor Chlumský 12 Oct 13, 2022