Lightweight, extremely high-performance JSON parser for C++11

Related tags

JSON sajson
Overview

Documentation

sajson

sajson is an extremely high-performance, in-place, DOM-style JSON parser written in C++.

Originally, sajson meant Single Allocation JSON, but it now supports dynamic allocation too.

Features

sajson parses an input document into a contiguous AST structure. Unlike some other high-performance JSON parsers, the AST is efficiently queryable. Object lookups by key are O(lg N) and array indexing is O(1).

sajson does not require that the input buffer is null-terminated. You can use it to parse straight out of a disk mmap or network buffer, for example.

sajson is in-situ: it modifies the input string. While parsing, string values are converted to UTF-8.

(Note: sajson pays a slight performance penalty for not requiring null termination of the input string. Because sajson is in-situ, many uses cases require copying the input data anyway. Therefore, I could be convinced to add an option for requiring null termination.)

Other Features

  • Single header file -- simply drop sajson.h into your project.
  • No exceptions, RTTI, or longjmp.
  • O(1) stack usage. No document will overflow the stack.
  • Only two number types: 32-bits and doubles.
  • Small code size -- suitable for Emscripten.
  • Has been fuzzed with American Fuzzy Lop.

AST Structure

The parsed AST's size is computed as such:

  • 2 words per string
  • 1 word per 32-bit integer value
  • 64 bits per floating point value
  • 1+N words per array, where N is the number of elements
  • 1+3N words per object, where N is the number of members

The values null, true, and false are encoded in tag bits and have no cost otherwise.

Allocation Modes

Single

The original sajson allocation mode allocates one word per byte of the input document. This is the fastest mode: because the AST and parse stack are guaranteed to fit, no allocation checks are required at runtime.

That is, on 32-bit platforms, sajson allocates 4 bytes per input character. On 64-bit platforms, sajson allocates 8 bytes per input character. Only use this parse mode if you can handle allocating the worst-case buffer size for your input documents.

Dynamic

The dynamic allocation mode grows the parse stack and AST buffer as needed. It's about 10-40% slower than single allocation because it needs to check for out-of-memory every time data is appended, and occasionally the buffers need to be reallocated and copied.

Bounded

The bounded allocation mode takes a fixed-size memory buffer and uses it for both the parse stack and the resulting AST. If the parse stack and AST fit in the given buffer, the parse succeeds. This allocation mode allows using sajson without the library making any allocations.

Performance

sajson's performance is excellent - it frequently benchmarks faster than RapidJSON, for example.

Implementation details are available at http://chadaustin.me/tag/sajson/.

Documentation

API documentation is available at http://chadaustin.github.io/sajson/doxygen/

Downsides / Missing Features

  • sajson does not support UTF-16 or UTF-32. However, I have never seen one of those in the wild, so I suspect they may be a case of aggressive overspecification. Some JSON specifications indicate that UTF-8 is the only valid encoding. Either way, just transcode to UTF-8 first.

  • No support for 64-bit integers. If this is something you want, just ask. (There's little technical reason not to support it. It's just that most people avoid 64-bit integers in JSON because JavaScript can't read them.)

  • Requires C++11. Some of the ownership semantics were awkward to express in C++03.

Comments
  • Parsing big integers

    Parsing big integers

    Hi,

    sajson interpret big numbers like 1496756396000 as double, because

                    if (SAJSON_UNLIKELY(!try_double && i > INT_MAX / 10 - 9)) {                                                                        
                        // TODO: could split this into two loops                                                                                       
                        try_double = true;                                                                                                             
                        d = i;                                                                                                                                         
                    } 
    

    Could you please fix that?

    opened by ksergey 6
  • Parsing failure

    Parsing failure

    I recently try to add sajson to nativejson-benchmark in this branch.

    It was able to parse two test json data, but failed for twitter.json. The error message generated is

    Verifying sajson (C++) ... Error (1:1): illegal unprintable codepoint in string
    

    with this code:

    class SajsonParseResult : public ParseResultBase {
    public:
        SajsonParseResult(document&& d_) : d(std::move(d_)) {}
        document d;
    };
    
    // ...
        virtual ParseResultBase* Parse(const char* json, size_t length) const {
            (void)length;
            SajsonParseResult* pr = new SajsonParseResult(parse(literal(json)));
            if (!pr->d.is_valid()) {
                std::cout << "Error (" << pr->d.get_error_line() << ":" << pr->d.get_error_column() << "): " << pr->d.get_error_message() << std::endl;
            }
            return pr;
        }
    

    I am pretty sure the json is valid, as it is obtained from twitter's API, and also passed more than a dozens of parsers.

    BTW, I am the author of RapidJSON :)

    opened by miloyip 6
  • undefined behaviour in integer_storage and double_storage

    undefined behaviour in integer_storage and double_storage

    After reading your blog post about sajson optimizations (it was a really interesting read) I started browsing the code. I noticed type-punning through a union:

        union integer_storage {
            enum {
                word_length = 1
            };
    
            static void store(size_t* location, int value) {
                integer_storage is;
                is.i = value;
                *location = is.u;
            }
    
            int i;
            size_t u;
        };
    

    From what I know from reading discussions on SO this is an undefined behavior in C++ (although a common practice). Just to let you know.

    (it's not a big deal; I think I'll start using this library soon anyway)

    opened by wojdyr 5
  • No allocation mode for sajson?

    No allocation mode for sajson?

    Hi, I'm wondering if it is possible to officially support using sajson without any allocation at all. Currently, even if one uses

    auto doc = sajson::parse(sajson::single_allocation(buffer, length), sajson::mutable_string_view(length, str));
    

    there will still be one allocation due to the use of refcount in mutable_string_view. In some applications allocations should be avoided as much as possible, but in this case sajson will still call operator new with a size of a size_t.

    I have a locally patched version of sajson that removes the use of refcount and changes mutable_string_view to only take unowned strings:

    --- a/sajson.h
    +++ b/sajson.h
    @@ -235,37 +235,13 @@ namespace sajson {
             mutable_string_view()
                 : length_(0)
                 , data(0)
    -            , owns(false)
             {}
    
             mutable_string_view(size_t length, char* data)
                 : length_(length)
                 , data(data)
    -            , owns(false)
             {}
    
    -        mutable_string_view(const literal& s)
    -            : length_(s.length())
    -            , owns(true)
    -        {
    -            data = new char[length_];
    -            memcpy(data, s.data(), length_);
    -        }
    -
    -        mutable_string_view(const string& s)
    -            : length_(s.length())
    -            , owns(true)
    -        {
    -            data = new char[length_];
    -            memcpy(data, s.data(), length_);
    -        }
    -
    -        ~mutable_string_view() {
    -            if (uses.count() == 1 && owns) {
    -                delete[] data;
    -            }
    -        }
    -
             size_t length() const {
                 return length_;
             }
    @@ -275,10 +251,8 @@ namespace sajson {
             }
    
         private:
    -        refcount uses;
             size_t length_;
             char* data;
    -        bool owns;
         };
    
         union integer_storage {
    

    I'm thinking perhaps sajson could incorporate something similar officially? Perhaps using an ifdef, or some more templating? If this sounds cool, I can proceed to make a PR.

    opened by kccqzy 5
  • Removing std::string from errors

    Removing std::string from errors

    I have a suggestion for a step towards removing the std::string dependency. Moving from error strings to error codes. You can see my implementation here: https://github.com/iboB/sajson/commit/5568a59286944dda72d8b554b20875ecf93b1654

    If you like it, I'll add a pull request

    opened by iboB 5
  • Documentation with API references

    Documentation with API references

    Hi,

    I've created a documentation with API references - https://sajson.docsforge.com/

    The docs are updated automatically so it will be in sync if the source files, readme, or examples are changed.

    If you want me to add or remove any pages (like namespace internal), please let me know :)

    Disclaimer, I'm the creator of docsforge.

    opened by erez-o 3
  • Question about invalid UTF-8

    Question about invalid UTF-8

    Hi! I am a spanish newbie with string encoding,

    I try:

    int main()
    {
    	std::string json = "{\"name\":\"áéíóúñ¡¿\"}";
    	size_t longitud = json.length();
    
    	char m_json[32];
    	strcpy(m_json, json.c_str());
    
    	const sajson::document& document = sajson::parse(sajson::dynamic_allocation(), 
            sajson::mutable_string_view(longitud, m_json));
    	if (!document.is_valid())
    	{
    	    return -1;
    	}
            return 0;
    }
    

    I get: ERROR_INVALID_UTF8 (22)

    How can solve this problem? I have test utilities like http://utfcpp.sourceforge.net/ for ensuring that a string contains valid UTF-8. And then it works! But... i don´t want to lose the original characters,,, (!)

    Thanks!

    DJuego

    opened by DJuego 3
  • Added get_value_of_key

    Added get_value_of_key

    it's a pretty common function when writing code to parse the json. In the test I added it's also shown what I write very often when using this function:

    objval.get_value_of_key(literal("b")).get_integer_value()

    opened by iboB 3
  • Unhandled error return value in sajson.h: parser::parse()

    Unhandled error return value in sajson.h: parser::parse()

    Within the parser::parse() function of sajson.h the return value of a call to parse_string() is ignored leading to a corrupt representation of the parsed objects.

    From sajson::parser::parse()

    if (current_structure_type == TYPE_OBJECT && c != '}') {
      if (c != '"') {
        return error("object key must be quoted");
      }
      result = parse_string(temp);
      if (peek_structure() != ':') {
        return error("expected :");
      }
      ++p;
      temp += 2;
    }
    

    When parsing an object key string the return value result of parse_string() is later overwritten. As long as the character following the string parsing error is a ':' and the value for the key is valid, the parser will overwrite that error return value before it is checked and parsing will continue as if the key string is valid.

    The bug can be demonstrated in a debugger using the following input to sajson::parser::parse()

    {"\:0}

    The initial object's key string is invalid and will generate an error within sajson::parser::parse_string_slow()

    switch (*p) {
    ...
    default:
      return error("unknown escape");
    

    This error value will be passed back to sajson::parser::parse() and written to the result variable. However, upon entering the following code the result variable will be overwritten with the return value of sajson::parser::parse_number().

    switch (peek_structure()) {
      type next_type;
      ...
      case '0':
      case '1':
      case '2':
      case '3':
      case '4':
      case '5':
      case '6':
      case '7':
      case '8':
      case '9':
      case '-':
        result = parse_number();
        break;
      ...
    if (!result) {
      return result.success;
    }
    

    When the value of result is finally checked the error value will no longer be present and parsing will continue with a bad element. In this simple case the parser does not crash.

    A more complicated object hierarchy can cause the parser to crash when the object containing the bad key is passed to sajson::parser::install_object(). The following input to sajson::parser::parse() can be used to demonstrate a crash when a corrupted object is sorted.

    {"":0,"":0,"":[0.,""],"\:[0.,""],"\:[]}

    The following patch can be implemented to correctly check the return value of sajson::parser::parse_string()

    diff --git a/include/sajson.h b/include/sajson.h
    index 350c58e..7ad08ad 100644
    --- a/include/sajson.h
    +++ b/include/sajson.h
    @@ -618,6 +618,9 @@ namespace sajson {
                             return error("object key must be quoted");
                         }
                         result = parse_string(temp);
    +                    if (!result) {
    +                        return result.success;
    +                    }
                         if (peek_structure() != ':') {
                             return error("expected :");
                         }
    
    opened by cneckar 3
  • 'parse_flags' redefinition ; different storage class

    'parse_flags' redefinition ; different storage class

    Hello Im trying to compile with visual studio 2015 and this error appears: 'parse_flags' redefinition ; different storage class

    This is located in sajson.h line 152 constexpr uint8_t globals_struct::parse_flags[256] = {

    Any idea?

    opened by mikelaltadi 2
  • warnings with -Wshadow

    warnings with -Wshadow

    The -Wshadow flag in GCC and Clang generates a number of warnings in sajson.h (copied below). This flag is not very popular, but on the other hand it'd not harm to avoid the warnings.

    $ g++-7 -c -std=c++11 -Wshadow -Iinclude example/main.cpp
    In file included from example/main.cpp:2:0:
    include/sajson.h: In constructor ‘sajson::string::string(const char*, size_t)’:
    include/sajson.h:221:13: warning: declaration of ‘text’ shadows a member of ‘sajson::string’ [-Wshadow]
                 : text(text)
                 ^
    include/sajson.h:240:27: note: shadowed declaration is here
             const char* const text;
                               ^~~~
    include/sajson.h: In constructor ‘sajson::literal::literal(const char*)’:
    include/sajson.h:251:13: warning: declaration of ‘text’ shadows a member of ‘sajson::literal’ [-Wshadow]
                 : string(text, strlen(text))
                 ^
    include/sajson.h:240:27: note: shadowed declaration is here
             const char* const text;
                               ^~~~
    include/sajson.h: In constructor ‘sajson::mutable_string_view::mutable_string_view(size_t, char*)’:
    include/sajson.h:271:13: warning: declaration of ‘data’ shadows a member of ‘sajson::mutable_string_view’ [-Wshadow]
                 : length_(length)
                 ^
    include/sajson.h:345:15: note: shadowed declaration is here
             char* data;
                   ^~~~
    include/sajson.h: In constructor ‘sajson::value::value(sajson::type, const size_t*, const char*)’:
    include/sajson.h:615:13: warning: declaration of ‘text’ shadows a member of ‘sajson::value’ [-Wshadow]
                 : value_type(value_type)
                 ^
    include/sajson.h:634:27: note: shadowed declaration is here
             const char* const text;
                               ^~~~
    include/sajson.h:615:13: warning: declaration of ‘payload’ shadows a member of ‘sajson::value’ [-Wshadow]
                 : value_type(value_type)
                 ^
    include/sajson.h:633:29: note: shadowed declaration is here
             const size_t* const payload;
                                 ^~~~~~~
    include/sajson.h:615:13: warning: declaration of ‘value_type’ shadows a member of ‘sajson::value’ [-Wshadow]
                 : value_type(value_type)
                 ^
    include/sajson.h:632:20: note: shadowed declaration is here
             const type value_type;
                        ^~~~~~~~~~
    include/sajson.h: In constructor ‘sajson::internal::ownership::ownership(size_t*)’:
    include/sajson.h:674:17: warning: declaration of ‘p’ shadows a member of ‘sajson::internal::ownership’ [-Wshadow]
                     : p(p)
                     ^
    include/sajson.h:691:21: note: shadowed declaration is here
                 size_t* p;
                         ^
    include/sajson.h: In constructor ‘sajson::internal::ownership::ownership(sajson::internal::ownership&&)’:
    include/sajson.h:678:13: warning: declaration of ‘p’ shadows a member of ‘sajson::internal::ownership’ [-Wshadow]
                 : p(p.p) {
                 ^
    include/sajson.h:691:21: note: shadowed declaration is here
                 size_t* p;
                         ^
    In file included from example/main.cpp:2:0:
    include/sajson.h: In constructor ‘sajson::document::document(const sajson::mutable_string_view&, sajson::internal::ownership&&, sajson::type, const size_t*)’:
    include/sajson.h:828:13: warning: declaration of ‘root’ shadows a member of ‘sajson::document’ [-Wshadow]
                 : input(input)
                 ^
    include/sajson.h:865:29: note: shadowed declaration is here
             const size_t* const root;
                                 ^~~~
    include/sajson.h:828:13: warning: declaration of ‘root_type’ shadows a member of ‘sajson::document’ [-Wshadow]
                 : input(input)
                 ^
    include/sajson.h:864:20: note: shadowed declaration is here
             const type root_type;
                        ^~~~~~~~~
    include/sajson.h:828:13: warning: declaration of ‘structure’ shadows a member of ‘sajson::document’ [-Wshadow]
                 : input(input)
                 ^
    include/sajson.h:863:29: note: shadowed declaration is here
             internal::ownership structure;
                                 ^~~~~~~~~
    include/sajson.h:828:13: warning: declaration of ‘input’ shadows a member of ‘sajson::document’ [-Wshadow]
                 : input(input)
                 ^
    include/sajson.h:862:29: note: shadowed declaration is here
             mutable_string_view input;
                                 ^~~~~
    include/sajson.h: In constructor ‘sajson::document::document(const sajson::mutable_string_view&, size_t, size_t, sajson::error, int)’:
    include/sajson.h:841:13: warning: declaration of ‘error_arg’ shadows a member of ‘sajson::document’ [-Wshadow]
                 : input(input)
                 ^
    include/sajson.h:869:19: note: shadowed declaration is here
             const int error_arg;
                       ^~~~~~~~~
    include/sajson.h:841:13: warning: declaration of ‘error_code’ shadows a member of ‘sajson::document’ [-Wshadow]
                 : input(input)
                 ^
    include/sajson.h:868:21: note: shadowed declaration is here
             const error error_code;
                         ^~~~~~~~~~
    include/sajson.h:841:13: warning: declaration of ‘error_column’ shadows a member of ‘sajson::document’ [-Wshadow]
                 : input(input)
                 ^
    include/sajson.h:867:22: note: shadowed declaration is here
             const size_t error_column;
                          ^~~~~~~~~~~~
    include/sajson.h:841:13: warning: declaration of ‘error_line’ shadows a member of ‘sajson::document’ [-Wshadow]
                 : input(input)
                 ^
    include/sajson.h:866:22: note: shadowed declaration is here
             const size_t error_line;
                          ^~~~~~~~~~
    include/sajson.h:841:13: warning: declaration of ‘input’ shadows a member of ‘sajson::document’ [-Wshadow]
                 : input(input)
                 ^
    include/sajson.h:862:29: note: shadowed declaration is here
             mutable_string_view input;
                                 ^~~~~
    include/sajson.h: In constructor ‘sajson::single_allocation::allocator::allocator(size_t*, size_t, bool)’:
    include/sajson.h:952:17: warning: declaration of ‘should_deallocate’ shadows a member of ‘sajson::single_allocation::allocator’ [-Wshadow]
                     : structure(buffer)
                     ^
    include/sajson.h:1022:18: note: shadowed declaration is here
                 bool should_deallocate;
                      ^~~~~~~~~~~~~~~~~
    include/sajson.h: In constructor ‘sajson::single_allocation::single_allocation(size_t*, size_t)’:
    include/sajson.h:1040:13: warning: declaration of ‘existing_buffer’ shadows a member of ‘sajson::single_allocation’ [-Wshadow]
                 : has_existing_buffer(true)
                 ^
    include/sajson.h:1077:17: note: shadowed declaration is here
             size_t* existing_buffer;
                     ^~~~~~~~~~~~~~~
    include/sajson.h: In constructor ‘sajson::single_allocation::single_allocation(size_t (&)[N])’:
    include/sajson.h:1049:13: warning: declaration of ‘existing_buffer’ shadows a member of ‘sajson::single_allocation’ [-Wshadow]
                 : single_allocation(existing_buffer, N)
                 ^
    include/sajson.h:1077:17: note: shadowed declaration is here
             size_t* existing_buffer;
                     ^~~~~~~~~~~~~~~
    include/sajson.h: In constructor ‘sajson::dynamic_allocation::allocator::allocator(size_t*, size_t, size_t)’:
    include/sajson.h:1198:17: warning: declaration of ‘initial_stack_capacity’ shadows a member of ‘sajson::dynamic_allocation::allocator’ [-Wshadow]
                     : ast_buffer_bottom(buffer)
                     ^
    include/sajson.h:1296:20: note: shadowed declaration is here
                 size_t initial_stack_capacity;
                        ^~~~~~~~~~~~~~~~~~~~~~
    include/sajson.h: In constructor ‘sajson::dynamic_allocation::dynamic_allocation(size_t, size_t)’:
    include/sajson.h:1304:13: warning: declaration of ‘initial_stack_capacity’ shadows a member of ‘sajson::dynamic_allocation’ [-Wshadow]
                 : initial_ast_capacity(initial_ast_capacity)
                 ^
    include/sajson.h:1336:16: note: shadowed declaration is here
             size_t initial_stack_capacity;
                    ^~~~~~~~~~~~~~~~~~~~~~
    include/sajson.h:1304:13: warning: declaration of ‘initial_ast_capacity’ shadows a member of ‘sajson::dynamic_allocation’ [-Wshadow]
                 : initial_ast_capacity(initial_ast_capacity)
                 ^
    include/sajson.h:1335:16: note: shadowed declaration is here
             size_t initial_ast_capacity;
                    ^~~~~~~~~~~~~~~~~~~~
    include/sajson.h: In constructor ‘sajson::bounded_allocation::stack_head::stack_head(sajson::bounded_allocation::allocator*)’:
    include/sajson.h:1399:17: warning: declaration of ‘source_allocator’ shadows a member of ‘sajson::bounded_allocation::stack_head’ [-Wshadow]
                     : source_allocator(source_allocator)
                     ^
    include/sajson.h:1402:24: note: shadowed declaration is here
                 allocator* source_allocator;
                            ^~~~~~~~~~~~~~~~
    include/sajson.h: In constructor ‘sajson::bounded_allocation::bounded_allocation(size_t*, size_t)’:
    include/sajson.h:1488:13: warning: declaration of ‘existing_buffer’ shadows a member of ‘sajson::bounded_allocation’ [-Wshadow]
                 : existing_buffer(existing_buffer)
                 ^
    include/sajson.h:1509:17: note: shadowed declaration is here
             size_t* existing_buffer;
                     ^~~~~~~~~~~~~~~
    include/sajson.h: In constructor ‘sajson::bounded_allocation::bounded_allocation(size_t (&)[N])’:
    include/sajson.h:1496:13: warning: declaration of ‘existing_buffer’ shadows a member of ‘sajson::bounded_allocation’ [-Wshadow]
                 : bounded_allocation(existing_buffer, N)
                 ^
    include/sajson.h:1509:17: note: shadowed declaration is here
             size_t* existing_buffer;
                     ^~~~~~~~~~~~~~~
    include/sajson.h: In constructor ‘sajson::parser<Allocator>::parser(const sajson::mutable_string_view&, Allocator&&)’:
    include/sajson.h:1520:13: warning: declaration of ‘allocator’ shadows a member of ‘sajson::parser<Allocator>’ [-Wshadow]
                 : input(msv)
                 ^
    include/sajson.h:2433:19: note: shadowed declaration is here
             Allocator allocator;
                       ^~~~~~~~~
    include/sajson.h: In member function ‘bool sajson::parser<Allocator>::parse()’:
    include/sajson.h:1746:22: warning: declaration of ‘success’ shadows a previous local [-Wshadow]
                     bool success;
                          ^~~~~~~
    include/sajson.h:1620:18: note: shadowed declaration is here
                 bool success;
                      ^~~~~~~
    include/sajson.h:1815:30: warning: declaration of ‘success’ shadows a previous local [-Wshadow]
                             bool success;
                                  ^~~~~~~
    include/sajson.h:1620:18: note: shadowed declaration is here
                 bool success;
                      ^~~~~~~
    include/sajson.h: In instantiation of ‘sajson::parser<Allocator>::parser(const sajson::mutable_string_view&, Allocator&&) [with Allocator = sajson::dynamic_allocation::allocator]’:
    include/sajson.h:2464:16:   required from ‘sajson::document sajson::parse(const AllocationStrategy&, const StringType&) [with AllocationStrategy = sajson::dynamic_allocation; StringType = sajson::mutable_string_view]’
    example/main.cpp:113:119:   required from here
    include/sajson.h:1519:9: warning: declaration of ‘allocator’ shadows a member of ‘sajson::parser<sajson::dynamic_allocation::allocator>’ [-Wshadow]
             parser(const mutable_string_view& msv, Allocator&& allocator)
             ^~~~~~
    include/sajson.h:2433:19: note: shadowed declaration is here
             Allocator allocator;
                       ^~~~~~~~~
    include/sajson.h: In instantiation of ‘bool sajson::parser<Allocator>::parse() [with Allocator = sajson::dynamic_allocation::allocator]’:
    include/sajson.h:1529:22:   required from ‘sajson::document sajson::parser<Allocator>::get_document() [with Allocator = sajson::dynamic_allocation::allocator]’
    include/sajson.h:2467:24:   required from ‘sajson::document sajson::parse(const AllocationStrategy&, const StringType&) [with AllocationStrategy = sajson::dynamic_allocation; StringType = sajson::mutable_string_view]’
    example/main.cpp:113:119:   required from here
    include/sajson.h:1746:22: warning: declaration of ‘success’ shadows a previous local [-Wshadow]
                     bool success;
                          ^~~~~~~
    include/sajson.h:1620:18: note: shadowed declaration is here
                 bool success;
                      ^~~~~~~
    include/sajson.h:1815:30: warning: declaration of ‘success’ shadows a previous local [-Wshadow]
                             bool success;
                                  ^~~~~~~
    include/sajson.h:1620:18: note: shadowed declaration is here
                 bool success;
                      ^~~~~~~
    
    opened by wojdyr 2
  • Extended functionality

    Extended functionality

    Thanks for an excellent library!

    I forked it to make some minor extensions, mainly overloaded operators for array indexing, object element access and value comparison.

    I could make a pull request from it but I don't know if you are interested in extending the library in this way!

    Anyway, the fork lives here: https://github.com/erikronstrom/sajson

    opened by erikronstrom 0
  • Reverts changes to sajson::globals_struct::parse_flags

    Reverts changes to sajson::globals_struct::parse_flags

    Hopefully fixes #48 Currently, sajson fails to compile with GCC. Previously, a problem with VS2015 were reported. This PR reverts parse_flags to how it was defined until 2020.

    opened by wojdyr 0
  • Confusing size description of passed buffer

    Confusing size description of passed buffer

    So we've had some problems with this: https://github.com/chadaustin/sajson/blob/eeaa7ee736ec2f826c7a30c0e340e5331d8efc57/include/sajson.h#L1115

    It says "size_in_words" which is a very unusual way to describe the size of a buffer. I'd say it's very not standard. Would it be possible to update this?

    opened by lundmark 2
  • Doesn't support relaxed root value restrictions in RFC 8259

    Doesn't support relaxed root value restrictions in RFC 8259

    All tests from nst/JSONTestSuite with a single value (string, number, boolean, or null) at the root fail with an error:

    document root must be object or array
    

    One example is y_structure_lonely_int.json:

    42
    

    If it weren't for this issue, then this parser would (AFAIK) be 100% conformant to RFC 8259.

    opened by Cebtenzzre 1
  • 64-bit Int

    64-bit Int

    Is there any hack to quickly add support for these? I use swift version and double representation of value is almost precise. Maybe I can cast payload somehow to Swift's Int? I've tried combinations of bit pattern and simple constructor casting but no success. Is it C++ library's engine limitation?

    opened by own2pwn 7
  • How to use Swift version?

    How to use Swift version?

    Hey there! I think switching enum with guard case . for every object in json isn't the best way, am I right? Could you show me real world (production) examples of using this lib?

    opened by own2pwn 10
Owner
Chad Austin
Chad Austin
A C++, header-only library for constructing JSON and JSON-like data formats, with JSON Pointer, JSON Patch, JSON Schema, JSONPath, JMESPath, CSV, MessagePack, CBOR, BSON, UBJSON

JSONCONS jsoncons is a C++, header-only library for constructing JSON and JSON-like data formats such as CBOR. For each supported data format, it enab

Daniel Parker 547 Jan 4, 2023
🔋 In-place lightweight JSON parser

?? JSON parser for C This is very simple and very powerful JSON parser. It creates DOM-like data structure and allows to iterate and process JSON obje

Recep Aslantas 23 Dec 10, 2022
Ultralightweight JSON parser in ANSI C

cJSON Ultralightweight JSON parser in ANSI C. Table of contents License Usage Welcome to cJSON Building Copying the source CMake Makefile Vcpkg Includ

Dave Gamble 8.3k Jan 4, 2023
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
JSON & BSON parser/writer

jbson is a library for building & iterating BSON data, and JSON documents in C++14. \tableofcontents Features # {#features} Header only. Boost license

Chris Manning 40 Sep 14, 2022
Jsmn is a world fastest JSON parser/tokenizer. This is the official repo replacing the old one at Bitbucket

JSMN jsmn (pronounced like 'jasmine') is a minimalistic JSON parser in C. It can be easily integrated into resource-limited or embedded projects. You

Serge Zaitsev 3.2k Jan 9, 2023
A JSON parser in C++

JSON++ Introduction JSON++ is a light-weight JSON parser, writer and reader written in C++. JSON++ can also convert JSON documents into lossless XML d

Hong Jiang 498 Dec 28, 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
Very low footprint JSON parser written in portable ANSI C

Very low footprint JSON parser written in portable ANSI C. BSD licensed with no dependencies (i.e. just drop the C file into your project) Never recur

James McLaughlin 1.2k Jan 5, 2023
Very simple C++ JSON Parser

Very simple JSON parser for c++ data.json: { "examples": [ { "tag_name": "a", "attr": [ { "key":

Amir Saboury 67 Nov 20, 2022
a JSON parser and printer library in C. easy to integrate with any model.

libjson - simple and efficient json parser and printer in C Introduction libjson is a simple library without any dependancies to parse and pretty prin

Vincent Hanquez 260 Nov 21, 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 fast JSON parser/generator for C++ with both SAX/DOM style API

A fast JSON parser/generator for C++ with both SAX/DOM style API Tencent is pleased to support the open source community by making RapidJSON available

Tencent 12.6k Dec 30, 2022
RapidJSON is a JSON parser and generator for C++.

A fast JSON parser/generator for C++ with both SAX/DOM style API

Tencent 12.6k Dec 30, 2022
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
Buggy JSON parser

Fuzzgoat: A minimal libFuzzer integration This repository contains a basic C project that includes an (intentionally insecure) JSON parser. It is an e

Fuzzbuzz 1 Apr 11, 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
Very low footprint JSON parser written in portable ANSI C

Very low footprint JSON parser written in portable C89 (sometimes referred to as ANSI C). BSD licensed with no dependencies (i.e. just drop the C file

null 1.2k Dec 23, 2022
A light-weight json parser.

pson pson is a lightweight parser and it support six type, null , bool, number, string, array, object, and it can parse the encoding of UTF-8. It's fa

pinK 17 Dec 1, 2022