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)

Comments
  • 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
  • misc improvements to json_serialize_to_buffer() performance

    misc improvements to json_serialize_to_buffer() performance

    Well, the bottleneck for the our use-case is sprintf() for numbers. There are too many numbers to convert on an embedded system.

    One minor improvement that I am still hesitant to push, is to return a pessimistic buf-size when json_serialization_size() gets called i.e. to return PARSON_NUM_BUF_SIZE instead of calling spritnf() (which would be a good performance booster). This changes some semantics (also in tests), where more memory would get allocated (thantneeded), but that wouldn't be too bad considering that sprintf() is too slow (which opens up a discussion about which is worse: speed or memory over-use).

    sprintf() performance is presented here: https://aras-p.info/blog/2022/02/25/Curious-lack-of-sprintf-scaling/

    So in this (patch) series, the idea (I am presenting) is that a user can/could provide their own serializer function for double/numbers (in case they don't like sprintf()). But I also included some minor perf stuff that I found along the way. The improvement (the other stuff adds) isl small, but (generally) they're still worth considering.

    Signed-off-by: Alexandru Ardelean [email protected]

    opened by commodo 5
  • scan-build bugs

    scan-build bugs

    Hi,

    I haven't investigated them, but there are 5 bugs that scan-build, a free static analysis tool, can detect in the parson code.

    image

    Running it is as simple as running those commands on Debian/Ubuntu:

    $ sudo apt install clang-tools  # install scan-build
    $ git clone https://github.com/kgabis/parson
    $ scan-build make
    $ scan-view …
    

    Hope this helps.

    opened by disconnect3d 0
  • Add vcpkg installation instructions

    Add vcpkg installation instructions

    parson is available as a port in vcpkg, a C++ library manager that simplifies installation for parson and other project dependencies. Documenting the install process here will help users get started by providing a single set of commands to build parson, ready to be included in their projects.

    We also test whether our library ports build in various configurations (dynamic, static) on various platforms (OSX, Linux, Windows: x86, x64) to keep a wide coverage for users.

    I'm a maintainer for vcpkg, and here is what the port script looks like. We try to keep the library maintained as close as possible to the original library. :)

    opened by FrankXie05 0
  • 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
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.2k Nov 19, 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 7 Oct 30, 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. 109 Nov 3, 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 17 Oct 19, 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 31 Nov 16, 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 544 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

Recep Aslantas 22 Sep 14, 2022
jq is a lightweight and flexible command-line JSON processor.

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

Stephen Dolan 23.7k Nov 26, 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 Nov 27, 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 Nov 17, 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 24 Sep 21, 2022
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 37 Nov 9, 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 Nov 27, 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 129 Oct 27, 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.8k Nov 18, 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 Nov 22, 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 124 Oct 26, 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
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 Nov 14, 2022