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 recurses or allocates more memory than it needs
  • Very simple API with operator sugar for C++

Build Status

Want to serialize? Check out json-builder!

Installing

There is now a makefile which will produce a libjsonparser static and dynamic library. However, this is not required to build json-parser, and the source files (json.c and json.h) should be happy in any build system you already have in place.

API

json_value * json_parse (const json_char * json,
                         size_t length);

json_value * json_parse_ex (json_settings * settings,
                            const json_char * json,
                            size_t length,
                            char * error);

void json_value_free (json_value *);

The type field of json_value is one of:

  • json_object (see u.object.length, u.object.values[x].name, u.object.values[x].value)
  • json_array (see u.array.length, u.array.values)
  • json_integer (see u.integer)
  • json_double (see u.dbl)
  • json_string (see u.string.ptr, u.string.length)
  • json_boolean (see u.boolean)
  • json_null

Compile-Time Options

-DJSON_TRACK_SOURCE

Stores the source location (line and column number) inside each json_value.

This is useful for application-level error reporting.

Runtime Options

settings |= json_enable_comments;

Enables C-style // line and /* block */ comments.

size_t value_extra

The amount of space (if any) to allocate at the end of each json_value, in order to give the application space to add metadata.

void * (* mem_alloc) (size_t, int zero, void * user_data);
void (* mem_free) (void *, void * user_data);

Custom allocator routines. If NULL, the default malloc and free will be used.

The user_data pointer will be forwarded from json_settings to allow application context to be passed.

Changes in version 1.1.0

  • UTF-8 byte order marks are now skipped if present

  • Allows cross-compilation by honoring --host if given (@wkz)

  • Maximum size for error buffer is now exposed in header (@LB--)

  • GCC warning for static after const fixed (@batrick)

  • Optional support for C-style line and block comments added (@Jin-W-FS)

  • name_length field added to object values

  • It is now possible to retrieve the source line/column number of a parsed json_value when JSON_TRACK_SOURCE is enabled

  • The application may now extend json_value using the value_extra setting

  • Un-ambiguate pow call in the case of C++ overloaded pow (@fcartegnie)

  • Fix null pointer de-reference when a non-existing array is closed and no root value is present

Owner
Comments
  • json fails on double value

    json fails on double value

    Fails with 1:104: Unexpected . in object

    { "status": "ok", "results": [ { "recordings": [ { "id": "889ec8e0-b8a6-4ff1-a104-5512ea49fe87" } ], "score": 0.879051, "id": "45047cb1-3d3f-477e-a3dc-f14e8254e78d" } ] }

  • Testing flags may not be correct.

    Testing flags may not be correct.

    VS2013 flagged a couple of possible issues and I'm not sure it it's right or not. Line 411:

    else if (!state.settings.settings & json_relaxed_commas)
    

    parses as ((!state.settings.settings) & json_relaxed_commas) and I think maybe it should be (!(state.settings.settings & json_relaxed_commas))

    And likewise line 572:

    if (flags & flag_need_comma && (!state.settings.settings & json_relaxed_commas))
    
  • Fix strict-aliasing warning

    Fix strict-aliasing warning

    A couple of lines trigger strict-aliasing warnings on gcc (Ubuntu)

    error: dereferencing type-punned pointer will break strict-aliasing rules [-Werror=strict-aliasing]
    

    Output of gcc --version

    gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
    

    This PR addresses those two warnings

    Commit d7b67db02aaa17fcc9bfbc8b60f41c3b677bd5a8 also simplifies the pointer notation by removing a reference and a dereference that seem to cancel each other out. Let's say that value->u.object.values is a pointer in memory location A and points to location B. Then | expression | type | pointer location | pointed location | |---|---|---|---| | value->u.object.values | json_object_entry * | A | B | | &value->u.object.values | json_object_entry ** | | A | | (char **) &value->u.object.values | char ** | | A | | *(char **) &value->u.object.values | char * | | B |

    The last expression can be simplified in (char *) value->u.object.values

  • Improve calculation of JSON_INT_MAX

    Improve calculation of JSON_INT_MAX

    From https://github.com/udp/json-parser/blob/e6426ae/json.c#L49-L55. That value can be calculated mathematically using 2**((n * 8) - 1) - 1. Which can also be done using the following bit shift:

    static const json_int_t JSON_INT_MAX = (1L << ((8 * sizeof(json_int_t) - 1))) - 1
    
  • Parse error when arrays are empty

    Parse error when arrays are empty

    Hi,

    The parser fails when the following JSON is provided: {"myArray": [] }

    In code: static char str[] = "{ "myArray": [] }"; json_value * root = json_parse(str, strlen(str));

    This is because malloc is called with a size of 0, due to the empty array. However some implementations of malloc will return NULL when asked to allocate 0 bytes and in this case the parser stops. I think this is wrong. In my opinion the parser should not try to allocate 0 bytes. A simple check in the newValue method for the json_array case can prevent this:

    In code: if (value->u.array.length == 0) { break; }

    With these three lines of code the parser can also handle the above input.

    Regards, Matthijs

  • Portability issue: cast from pointer to unsigned long

    Portability issue: cast from pointer to unsigned long

    The compiler on my system is 64 bit and sizeof(void *) is 8.

    json-parser\json.c: In function 'new_value':
    json-parser\json.c:135:42: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
                       (state, values_size + ((unsigned long) value->u.object.values), 0)) )
                                              ^
    

    https://github.com/udp/json-parser/blob/master/json.c#L141 In context, I'm not sure what this is supposed to be doing, so I don't have a proposed solution.

  • Compile error using clang

    Compile error using clang

    [100%] Building C object AudioAgent/external/CMakeFiles/JsonParser.dir/json-parser/json.c.o cc: warning: argument unused during compilation: '-no-cpp-precomp' /Users/johank/safe/audio/trunk/AudioAgent/external/json-parser/json.c:42:51: error: missing field 'type' initializer [-Werror,-Wmissing-field-initializers] const struct _json_value json_value_none = { 0 }; ^ I would suggest changing to

    const struct _json_value json_value_none;

    since static variables should anyway be zero initialized by default.

  • Raisonance RC51 error

    Raisonance RC51 error

    Hey

    I just tried compiling this with Raisonance's RC51 compiler, and it threw this error:

    *** ERROR C203 IN LINE 638 OF json.c : '(XDATA  CODE)': pointer: different mspace
    

    on the first lines of e_failed.

    With those lines commented out it worked fine.

  • Use size_t for memory size

    Use size_t for memory size

    The C standard library consistently uses size_t for variables related to memory size. See for example malloc(), memset(), sizeof().

    The maximum value of an object of size_t type is:

    Note that we cannot change unsigned longto size_t everywhere without modifying the API, so we will probably have to live with this exception:

    typedef struct
    {
       unsigned long max_memory;
       [...]
    } json_settings;
    
  • Copyright dates and web site updates

    Copyright dates and web site updates

    Perhaps it's time we change:

     * Copyright (C) 2012, 2013, 2014, 2016, 2018, 2019, 2021 James McLaughlin et al.  All rights reserved.
    

    to:

     * Copyright (C) 2012-2021 James McLaughlin et al.  All rights reserved.
    
  • Fix header files

    Fix header files

    json.h: <inttypes.h><stdint.h> int64_t is defined in <stdint.h>, no need for the full <inttypes.h>

    json.h: <stdlib.h><stddef.h> <stddef.h> is enough to define size_t

    json.c: <stdlib.h> Now that <stdlib.h> has been removed from json.h, add it to json.c for malloc()/calloc() and free()

  • Potential buffer overflow

    Potential buffer overflow

    I came across your library while investigating security of a widely deployed product using it. I found the overflow checks to be very lacking.

    The calculations performed under https://github.com/json-parser/json-parser/blob/94f66d8f83c1d84ccccd7540ec2f51cf8325d272/json.c#L154 and https://github.com/json-parser/json-parser/blob/94f66d8f83c1d84ccccd7540ec2f51cf8325d272/json.c#L167 can overflow even if length stays below UINT_MAX. For 32 bit applications both size_t and unsigned int are 32 bit values. As a result, this code can handle at most 0x40000000 array entries and at most 0x13B13B13 object entries before the allocation size overflows resulting in far too little memory being allocated. Once array/object data is written into this buffer, it overflows which could result in code execution.

    Luckily, this allocation only happens in the second pass. Your code will allocate all the json_value instances in the first pass however, resulting in an out of memory error before this allocation can be reached. So with the current logic this buffer overflow vulnerability doesn’t seem exploitable. It might turn exploitable however if you change the allocation pattern or implement a streaming mode. So I sincerely recommend fixing this ASAP.

    I’m not sure what the best course of action is here. gcc and clang compilers allow you to perform arithmetic operations with overflow checking. I suspect that you cannot expect these builtins to exist however. So in case where you don’t have them, maybe https://www.fefe.de/intof.html is of help to construct similar functionality.

    It might be a good idea to also drop the current overflow checks which rely on sizes never growing by more than 8 at once. Instead, whenever you increase a length you should use addition with overflow checking.

  • What is allocated?

    What is allocated?

    The description says that this library never allocates more memory than it needs. That's nice but what is needed? Other JSON parser libs make explicit statements about whether they allocate any memory for the parsed data. This one looks like it needs to allocate memory for all parsed values, including all strings (providing a zero-terminated copy) and also those object keys that I'm not interested in. I'm looking for a JSON parser to use on an ESP32 microcontroller in conjunction with MQTT and WiFi. There is some RAM available but I'd like to keep its use for this task to a minimum.

    I don't need the original JSON string anymore after parsing, so destroying it and providing pointers into it would be fine with me (adding terminating zero and shifting backslash sequences in-place).

    If that's not supported, would I be able to prevent running out of memory by limiting the accepted JSON string length so something reasonable for my application?

  • Upgrade CodeQL and GitHub Actions

    Upgrade CodeQL and GitHub Actions

    CodeQL Action v1 will be deprecated on December 7th, 2022.

    For more information, see: https://github.blog/changelog/2022-04-27-code-scanning-deprecation-of-codeql-action-v1/

  • Runtime error when running with clang -fsanitize=undefined

    Runtime error when running with clang -fsanitize=undefined

    To reproduce, I built the code 'examples' with the following command on my mac:

    cd examples
    clang test_json.c ../json.c -I ../ -fsanitize=undefined
    

    Then when I run:

    ./a.out ../tests/valid-0000.json
    

    I get this runtime warning:

    ../json.c:437:34: runtime error: applying non-zero offset 8 to null pointer
    

    It seems to work if I replace in the code the line:

    json_car **char = (json_char **) &top->u.object.values;
    

    by:

    intptr_t *chars = (intptr_t *) &top->u.object.values;
    
  • New bversion?

    New bversion?

    Looking on https://github.com/json-parser/json-parser/compare/v1.1.0...master I think that it would be good to flush all those commits and make new release.

  • Install pkgconfig file to $(libdir)

    Install pkgconfig file to $(libdir)

    Pkgconfig file needs to be installed in $(libdir) rather than $(datadir), otherwise it is not possible to support multilib systems properly, e.g. 32 and 64 bits library on one system, where location must differ /usr/lib/pkgconfig for 32bit and /usr/lib64/pkgconfig for 64bit, for example.

Related tags
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-

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

Nov 26, 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

Dec 3, 2022
Very simple C++ JSON Parser

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

Nov 20, 2022
A very sane (header only) C++14 JSON library

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

Nov 28, 2022
Very fast Python JSON parsing library

cysimdjson Fast JSON parsing library for Python, 7-12 times faster than standard Python JSON parser. It is Python bindings for the simdjson using Cyth

Nov 20, 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

Nov 27, 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

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

Dec 6, 2022
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

Dec 1, 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

Dec 1, 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

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

Dec 4, 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

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

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

sajson sajson is an extremely high-performance, in-place, DOM-style JSON parser written in C++. Originally, sajson meant Single Allocation JSON, but i

Nov 17, 2022
🔋 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

Sep 14, 2022
RapidJSON is a JSON parser and generator for C++.
RapidJSON is a JSON parser and generator for C++.

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

Dec 7, 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

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

Apr 11, 2022