Very small JSON parser written in C.


  • Parses JSON from null-terminated string
  • Easy to use tree traversal API
  • Allows // line and /* block */ comments (except before colon ':')
  • Operates on single-byte or multi-byte characters (like UTF-8), but not on wide characters
  • Unescapes string values (including Unicode codepoints & surrogates)
  • Can use custom Unicode encoder, UTF-8 encoder built in
  • Can use custom memory allocator
  • Can use custom macro to print errors
  • Test suite included


  • Non-validating parser; might accept invalid JSON (eg., extra or missing commas, comments, octal or hex numeric values, etc.)


Parsed JSON tree consists of nodes. Each node has type:

typedef enum nx_json_type {
  NX_JSON_NULL,    // this is null value
  NX_JSON_OBJECT,  // this is an object; properties can be found in child nodes
  NX_JSON_ARRAY,   // this is an array; items can be found in child nodes
  NX_JSON_STRING,  // this is a string; value can be found in text_value field
  NX_JSON_INTEGER, // this is an integer; value can be found in int_value field
  NX_JSON_DOUBLE,  // this is a double; value can be found in dbl_value field
  NX_JSON_BOOL     // this is a boolean; value can be found in int_value field
} nx_json_type;

The node itself:

typedef struct nx_json {
  nx_json_type type;       // type of json node, see above
  const char* key;         // key of the property; for object's children only
  const char* text_value;  // text value of STRING node
  long int_value;          // the value of INTEGER or BOOL node
  double dbl_value;        // the value of DOUBLE node
  int length;              // number of children of OBJECT or ARRAY
  nx_json* child;          // points to first child
  nx_json* next;           // points to next child
} nx_json;


const nx_json* nx_json_parse(char* text, nx_json_unicode_encoder encoder);

Parses null-terminated string text into nx_json tree structure. The string is modified in place.

Parsing ends right after retrieving first valid JSON value. Remainder of the text is not analysed.

Returns NULL on syntax error. Error details are printed out using user-redefinable macro NX_JSON_REPORT_ERROR(msg, ptr).

Inside parse function nx_json nodes get allocated using user-redefinable macro NX_JSON_CALLOC() and freed by NX_JSON_FREE(json).

All text_value pointers refer to the content of original text string, which is modified in place to unescape and null-terminate JSON string literals.

encoder is a function defined as follows:

int unicode_to_my_encoding(unsigned int codepoint, char* p, char** endp) { ... }

Encoder takes Unicode codepoint and writes corresponding encoded value into buffer pointed by p. It should store pointer to the end of encoded value into *endp. The function should return 1 on success and 0 on error. Number of bytes written must not exceed 6.

NXJSON includes sample encoder nx_json_unicode_to_utf8, which converts all \uXXXX escapes into UTF-8 sequences.

In case encoder parameter is NULL all unicode escape sequences (\uXXXX) are ignored (remain untouched).

const nx_json* nx_json_parse_utf8(char* text);

This is shortcut for nx_json_parse(text, nx_json_unicode_to_utf8) where nx_json_unicode_to_utf8 is unicode to UTF-8 encoder provided by NXJSON.

void nx_json_free(const nx_json* js);

Frees resources (nx_json nodes) allocated by nx_json_parse().


const nx_json* nx_json_get(const nx_json* json, const char* key);

Gets object's property by key.

If json points to OBJECT node returns first the object's property identified by key key.

If there is no such property returns dummy node of type NX_JSON_NULL. Never returns literal NULL.

const nx_json* nx_json_item(const nx_json* json, int idx);

Gets array's item by its index.

If json points to ARRAY node returns array's element identified by index idx.

If json points to OBJECT node returns object's property identified by index idx.

If there is no such item/property returns dummy node of type NX_JSON_NULL. Never returns literal NULL.

Usage Example

JSON code:

  "some-int": 195,
  "array": [ 3, 5.1, -7, "nine", /*11*/ ],
  "some-bool": true,
  "some-dbl": -1e-4,
  "some-null": null,
  "hello": "world!",
  //"other": "/OTHER/",
  "obj": {"KEY": "VAL"}


const nx_json* json=nx_json_parse(code, 0);
if (json) {
  printf("some-int=%ld\n", nx_json_get(json, "some-int")->int_value);
  printf("some-dbl=%lf\n", nx_json_get(json, "some-dbl")->dbl_value);
  printf("some-bool=%s\n", nx_json_get(json, "some-bool")->int_value? "true":"false");
  printf("some-null=%s\n", nx_json_get(json, "some-null")->text_value);
  printf("hello=%s\n", nx_json_get(json, "hello")->text_value);
  printf("other=%s\n", nx_json_get(json, "other")->text_value);
  printf("KEY=%s\n", nx_json_get(nx_json_get(json, "obj"), "KEY")->text_value);
  const nx_json* arr=nx_json_get(json, "array");
  int i;
  for (i=0; i<arr->length; i++) {
    const nx_json* item=nx_json_item(arr, i);
    printf("arr[%d]=(%d) %ld %lf %s\n", i, (int)item->type, item->int_value, item->dbl_value, item->text_value);



Copyright (c) 2013 Yaroslav Stavnichiy