Lightweight JSON library written in C.

Overview

About

Parson is a lightweight json library written in C.

Features

  • Full JSON support
  • Lightweight (only 2 files)
  • Simple API
  • Addressing json values with dot notation (similar to C structs or objects in most OO languages, e.g. "objectA.objectB.value")
  • C89 compatible
  • Test suites

Installation

Run:

git clone https://github.com/kgabis/parson.git

and copy parson.h and parson.c to you source code tree.

Run make test to compile and run tests.

Examples

Parsing JSON

Here is a function, which prints basic commit info (date, sha and author) from a github repository.

void print_commits_info(const char *username, const char *repo) {
    JSON_Value *root_value;
    JSON_Array *commits;
    JSON_Object *commit;
    size_t i;
    
    char curl_command[512];
    char cleanup_command[256];
    char output_filename[] = "commits.json";
    
    /* it ain't pretty, but it's not a libcurl tutorial */
    sprintf(curl_command, 
        "curl -s \"https://api.github.com/repos/%s/%s/commits\" > %s",
        username, repo, output_filename);
    sprintf(cleanup_command, "rm -f %s", output_filename);
    system(curl_command);
    
    /* parsing json and validating output */
    root_value = json_parse_file(output_filename);
    if (json_value_get_type(root_value) != JSONArray) {
        system(cleanup_command);
        return;
    }
    
    /* getting array from root value and printing commit info */
    commits = json_value_get_array(root_value);
    printf("%-10.10s %-10.10s %s\n", "Date", "SHA", "Author");
    for (i = 0; i < json_array_get_count(commits); i++) {
        commit = json_array_get_object(commits, i);
        printf("%.10s %.10s %s\n",
               json_object_dotget_string(commit, "commit.author.date"),
               json_object_get_string(commit, "sha"),
               json_object_dotget_string(commit, "commit.author.name"));
    }
    
    /* cleanup code */
    json_value_free(root_value);
    system(cleanup_command);
}

Calling print_commits_info("torvalds", "linux"); prints:

Date       SHA        Author
2012-10-15 dd8e8c4a2c David Rientjes
2012-10-15 3ce9e53e78 Michal Marek
2012-10-14 29bb4cc5e0 Randy Dunlap
2012-10-15 325adeb55e Ralf Baechle
2012-10-14 68687c842c Russell King
2012-10-14 ddffeb8c4d Linus Torvalds
...

Persistence

In this example I'm using parson to save user information to a file and then load it and validate later.

void persistence_example(void) {
    JSON_Value *schema = json_parse_string("{\"name\":\"\"}");
    JSON_Value *user_data = json_parse_file("user_data.json");
    char buf[256];
    const char *name = NULL;
    if (user_data == NULL || json_validate(schema, user_data) != JSONSuccess) {
        puts("Enter your name:");
        scanf("%s", buf);
        user_data = json_value_init_object();
        json_object_set_string(json_object(user_data), "name", buf);
        json_serialize_to_file(user_data, "user_data.json");
    }
    name = json_object_get_string(json_object(user_data), "name");
    printf("Hello, %s.", name);
    json_value_free(schema);
    json_value_free(user_data);
    return;
}

Serialization

Creating JSON values is very simple thanks to the dot notation. Object hierarchy is automatically created when addressing specific fields. In the following example I create a simple JSON value containing basic information about a person.

void serialization_example(void) {
    JSON_Value *root_value = json_value_init_object();
    JSON_Object *root_object = json_value_get_object(root_value);
    char *serialized_string = NULL;
    json_object_set_string(root_object, "name", "John Smith");
    json_object_set_number(root_object, "age", 25);
    json_object_dotset_string(root_object, "address.city", "Cupertino");
    json_object_dotset_value(root_object, "contact.emails", json_parse_string("[\"[email protected]\",\"[email protected]\"]"));
    serialized_string = json_serialize_to_string_pretty(root_value);
    puts(serialized_string);
    json_free_serialized_string(serialized_string);
    json_value_free(root_value);
}

Output:

{
    "name": "John Smith",
    "age": 25,
    "address": {
        "city": "Cupertino"
    },
    "contact": {
        "emails": [
            "[email protected]",
            "[email protected]"
        ]
    }
}

Contributing

I will always merge working bug fixes. However, if you want to add something new to the API, please create an "issue" on github for this first so we can discuss if it should end up in the library before you start implementing it. Remember to follow parson's code style and write appropriate tests.

My other projects

  • ape - simple programming language implemented in C library
  • kgflags - easy to use command-line flag parsing library
  • agnes - header-only NES emulation library

License

The MIT License (MIT)

Issues
  • Excess precision for small floating point numbers.

    Excess precision for small floating point numbers.

    The following program gives the following output:

    {"value":0.59999999999999998}

    This is undesireable. How can I avoid it?

    int main() { JSON_Value* json_val = json_value_init_object(); json_object_set_number(json_object(json_val), "value", 0.6);
    char* json_str = json_serialize_to_string(json_val); printf("%s\n", json_str); json_free_serialized_string(json_str); json_value_free(json_val); }

    wontfix 
    opened by sgh 16
  • Build using meson

    Build using meson

    Meson is much easier to read and write compared to Cmake and Make. I added Meson to parson here. Meson support allows parson to be integrated as a subproject if parson is not installed on the system.

    opened by uni-dos 13
  • Found a bug!

    Found a bug!

    STREQ(json_object_get_string(root_object, "utf string"), "lorem ipsum中华人2民共和国")- FAIL STREQ(json_object_get_string(root_object, "utf-8 string"), "中国あいうえお")- FAIL

    opened by shu7734 13
  • Buffer overrun

    Buffer overrun

    Hi, i tried using your lib to generate logs, which works fine for simple cases. I'm currently using VS2008 and will also use gcc.

    But as soon as I add a longer message containing backslashes I do get a crash calling json_serialize_to_string():

    const char* msg = "Environment: \npid=13232\nhostname=con-js\nALLUSERSPROFILE=C:\ProgramData\nAPPDATA=C:\Users\js\AppData\Roaming";
    JSON_Value *root_value = json_value_init_object();
    JSON_Object *root_object = json_value_get_object(root_value);
    char *serialized_string = NULL;
    json_object_set_string(root_object, "message", msg);
    serialized_string = json_serialize_to_string(root_value);
    json_free_serialized_string(serialized_string);
    json_value_free(root_value);
    

    It looks like json_serialize_string writes over the bounds of buf, which causes to stop.

    The call stack:

    msvcr90.dll!_crt_debugger_hook(int _Reserved=12770140)  Zeile 65    C
    msvcr90.dll!_invalid_parameter(const wchar_t * pszExpression=0x00000000, const wchar_t * pszFunction=0x00000000, const wchar_t * pszFile=0x00000000, unsigned int nLine=0, unsigned int pReserved=0)  Zeile 112 + 0x7 Bytes C++
    msvcr90.dll!sprintf(char * string=0x00000000, const char * format=0x040baff0, ...)  Zeile 105 + 0x1c Bytes  C
    _cdbwrapc.pyd!json_serialize_to_buffer_r(const json_value_t * value=0x0490c068, char * buf=0x00000000)  Zeile 698 + 0xf Bytes   C
    _cdbwrapc.pyd!json_serialize_to_buffer(const json_value_t * value=0x0490c068, char * buf=0x0496a380, unsigned int buf_size_in_bytes=97)  Zeile 1075 + 0xd Bytes C
    _cdbwrapc.pyd!json_serialize_to_string(const json_value_t * value=0x0490c068)  Zeile 1107 + 0x11 Bytes  C
    

    Am I guessing right, or did you watch similar behaviour before?

    opened by stuertz 11
  • Add support for per-node floating point format (for numbers)

    Add support for per-node floating point format (for numbers)

    I have the patch here: https://gist.github.com/jamesbond3142/19a857d2cc31e2fd550f8fd129d5802f It's quick and dirty and the format is supposed to be constant (not malloc-ed or snprintf etc) as no memory management is done for that. Backward compatible (I created new function name).

    opened by jamesbond3142 10
  • I recive null on socket response parsing

    I recive null on socket response parsing

    Please, take a little look to this SOpt post, i have an inssue with parsing response data. http://pt.stackoverflow.com/q/148202/8984?problema-com-a-library-parson-ao-utilizar-json-object-get-string-com-resposta-do

    JSON_Value const *user_data = json_parse_string(response);
    const char *msgs = json_object_get_string(json_object(user_data), "message");
    __android_log_print(ANDROID_LOG_INFO, "-----from--jni-1-----", "Json Message  1. [%s] \n", msgs);
    

    example I/-----from--jni-1-----: Json Message 1. [(null)]

    response: {"name":"qualquer um", "message":"ano 2016"}

    What is going on with this code? @kgabis

    invalid 
    opened by MythodeaLoL 9
  • STM32 Problems with keil uvision 5

    STM32 Problems with keil uvision 5

    Hi, I tried to insert in the uvision 5 the parson.c and parson.h but the test result is mistaken. The function:

    • json_object_dotset_string(root_object, "address.city", "Cupertino");
    • json_object_dotset_value(root_object, "contact.emails", json_parse_string("["[email protected]","[email protected]"]")); aren't correct response. json 6 seriale 6

    For further infomation I enclose the prints and the serial output. Can you help me? Thanks

    opened by sfranchin63 8
  • JSON objects inside JSON Array

    JSON objects inside JSON Array

    Hello,

    Is there any way to insert JSON objects in to JSON Array? Eg:- "employees":[ {"firstName":"John", "lastName":"Doe"}, {"firstName":"Anna", "lastName":"Smith"}, {"firstName":"Peter","lastName":"Jones"} ] I tried to parse the string in the above format and put it in to an array using json_parse_string(). Which I couldn't succeed.

    Could you give some pointers to this?

    Thanks, Sajeesh.

    opened by sajeeshknair 7
  • Convert large strings to JSON_Value*

    Convert large strings to JSON_Value*

    I'm have been using for a long time the function json_parse_string, but now I need convert a large string (json array with 300 positions), the length is about 11k caracters, and the function return NULL. Is there any length limit to convert ?

    opened by bkonno 6
  • Adds travis support, with README badge

    Adds travis support, with README badge

    Go to https://travis-ci.org/profile/kgabis in order to enable the travis testing on this repository. Once this is done, every PR (and direct pushes too) will be tested automatically when it is open. You will also have to authorize travis as an oauth app for your profile.

    Note: If you merge this PR after #76, you will need to append make tests in the .travis.yml file. If you merge it before, you will need to append that line in #76.

    opened by 7heo 6
  • Having a JSON object within a JSON array

    Having a JSON object within a JSON array

    Hello,

    I am trying to have something like this printed in a string:

    { "serial": "1234", "device": "5", "data": { "enabled": true, "fw_version": "12345" }, "log_data": [ { "time": 123456, "sensor1": 12 }, { "time": 123456, "sensor2": 12 } ] }

    I used the code provided in this old thread but I can't get around it. It doesn't work

    `void serialization_example1(void) { JSON_Value *root = json_value_init_object(); JSON_Value *arrayRecord = json_value_init_object(); JSON_Object *root_object = json_value_get_object(root); char *buf_ext = NULL;

    json_object_dotset_value(root_object, "log_data", json_value_init_array());

    json_object_set_string(root_object, "time", "123456"); json_object_set_number(root_object, "sensor1", "12");

    appendArrayRecord(root, "log_data", arrayRecord); buf_ext = json_serialize_to_string_pretty(root);

    puts(buf_ext);

    return; } `

    this is my code but my output looks like:

    { "log_data": [ {} ], "time": "123456" "sensor1": 12 }

    I would like instead the "time" and "sensor1" to be nested inside log_data, as the original poster was asking. What am I missing in the code?

    Many thanks

    opened by clash90 5
  • create callbacks to be able to overwrite file i/o functions

    create callbacks to be able to overwrite file i/o functions

    one of the applicatiosn of this library is on embedded systems, where functions such as fopen cannot be taken from <stdio.h>. It'd be nice if we could leave the functions from stdio.h as default but give the user the option to overwrite them via callbacks (similiar to what you did with malloc and free).

    opened by hazemati 1
  • is_decimal: Fix an integer underflow.

    is_decimal: Fix an integer underflow.

    It seems harmless though.

    Found by UBSAN

    parson.c:270:18: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'size_t' (aka 'unsigned long')

    opened by yamt 0
  • Remove redundant code

    Remove redundant code

    Found by clang-check. (the last one looks like a false-positive to me)

    parson.c:995:17: warning: Value stored to 'buf' is never read buf += written; ^ ~~~~~~~ parson.c:1016:17: warning: Value stored to 'buf' is never read buf += written; ^ ~~~~~~~ parson.c:1834:24: warning: Array access (via field 'names') results in a null pointer dereference if (strcmp(object->names[i], name) == 0) { ^~~~~~~~~~~~~~~~ 3 warnings generated.

    opened by yamt 0
  • Added fuzzer with seed corpus

    Added fuzzer with seed corpus

    Adding a fuzzer to suggest integration with oss-fuzz.

    Integrating Parson with oss-fuzz allows Google to run the fuzzer on their infrastructure continuously. The maintainers of Parson get reports via email whenever a bug is found. It is expected that the maintainers fix these bugs, so the fuzzer can go on and test for other bugs.

    If you would like to integrate, please leave a comment with an email address that can be used as a contact email over on oss-fuzz, and let me know who to add on the cc-list for bug reports.

    I have a few more additions to the fuzzers, but at this point it gets decent coverage and stops from a buffer-overflow.

    Having it in the tests-folder will help other contributors to quickly locate it, but if you would like it elsewhere, it is no problem.

    I would like to add myself to the cc-list to monitor bugs and fixes, so I can keep working on improving the fuzzing-efforts on the oss-fuzz integration.

    Once I have your confirmation to integrate, I will setup the build files on oss-fuzz and make sure it builds correctly. That should allow the maintainers of oss-fuzz to evaluate the integration.

    opened by AdamKorcz 0
  • Unused macro, misleading comments regarding `sscanf`

    Unused macro, misleading comments regarding `sscanf`

    Commit 96150ba removed all calls to sscanf, but it's still referenced in a comment here: https://github.com/kgabis/parson/blob/master/parson.c#L594

    I don't know how much (if any) of this comment is still accurate.

    This same commit added the line #define sscanf THINK_TWICE_ABOUT_USING_SSCANF

    This is a logical way to prevent use of this function, but recent compilers will warn about unused macros (and often this warning is enabled by -Wall or -Wextra).

    I propose either of these fixes to remove this warning:

    • explicitly pass -Wno-unused-macros to gcc
    • remove the macro from the source file and pass -D sscanf=THINK_TWICE_ABOUT_USING_SSCANF to gcc
    opened by dan-so 0
Owner
Krzysztof Gabis
Krzysztof Gabis
Lightweight JSON library written in C.

About Parson is a lightweight json library written in C. Features Full JSON support Lightweight (only 2 files) Simple API Addressing json values with

Krzysztof Gabis 1.1k Jul 31, 2022
json-cpp is a C++11 JSON serialization library.

JSON parser and generator for C++ Version 0.1 alpha json-cpp is a C++11 JSON serialization library. Example #include <json-cpp.hpp> struct Foo {

Anatoly Scheglov 4 Dec 31, 2019
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. 108 Jul 7, 2022
A convenience C++ wrapper library for JSON-Glib providing friendly syntactic sugar for parsing JSON

This library is a wrapper for the json-glib library that aims to provide the user with a trivial alternative API to the API provided by the base json-

Rob J Meijer 16 May 10, 2022
json-build is a zero-allocation JSON serializer compatible with C89

json-build is a zero-allocation JSON serializer compatible with C89. It is inspired by jsmn, a minimalistic JSON tokenizer.

Lucas Müller 27 Jul 26, 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

Chad Austin 538 Jul 27, 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

Recep Aslantas 21 Jun 7, 2022
jq is a lightweight and flexible command-line JSON processor.

jq is a lightweight and flexible command-line JSON processor.

Stephen Dolan 22.7k Aug 2, 2022
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 Jul 28, 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 Jul 28, 2022
An easy-to-use and competitively fast JSON parsing library for C++17, forked from Bitcoin Cash Node's own UniValue library.

UniValue JSON Library for C++17 (and above) An easy-to-use and competitively fast JSON parsing library for C++17, forked from Bitcoin Cash Node's own

Calin Culianu 10 Aug 31, 2021
A Haskell library for fast decoding of JSON documents using the simdjson C++ library

hermes A Haskell interface over the simdjson C++ library for decoding JSON documents. Hermes, messenger of the gods, was the maternal great-grandfathe

Josh Miller 36 Jun 29, 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 Aug 4, 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 Jun 7, 2022
A C++ library for interacting with JSON.

JsonCpp JSON is a lightweight data-interchange format. It can represent numbers, strings, ordered sequences of values, and collections of name/value p

null 6.6k Aug 4, 2022
A tiny JSON library for C++11.

json11 json11 is a tiny JSON library for C++11, providing JSON parsing and serialization. The core object provided by the library is json11::Json. A J

Dropbox 2.4k Aug 6, 2022
A killer modern C++ library for interacting with JSON.

JSON Voorhees Yet another JSON library for C++. This one touts new C++11 features for developer-friendliness, an extremely slow-speed parser and no de

Travis Gockel 125 Mar 4, 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 262 Aug 6, 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 268 Aug 8, 2022