JSON Parser (json)
JSON parser that parses JSON text into a tree of json_value_t nodes, supporting all standard JSON types (object, array, integer, double, string, boolean, null).
Parser characteristics:
- Single file, no external dependencies. Uses two-pass scanning (measure first, then allocate); the total number of memory allocations is O(N) in the node count.
- Integers use
int64_t; on overflow they are automatically promoted todouble. - Full support for
\uXXXXescapes, UTF-16 surrogate pairs, and UTF-8 output. - UTF-8 BOM (
EF BB BF) is skipped automatically. - C-style comments
//and/* */are accepted (non-standard JSON extension). - Input is read by
lengthbytes; embedded\0is allowed and the buffer does not need to be NUL-terminated.
Data Structures
enum json_type_t {
JSON_NONE,
JSON_OBJECT,
JSON_ARRAY,
JSON_INTEGER,
JSON_DOUBLE,
JSON_STRING,
JSON_BOOLEAN,
JSON_NULL,
};
struct json_value_t {
struct json_value_t * parent;
enum json_type_t type;
union {
int boolean;
int64_t integer;
double dbl;
struct { unsigned int length; char * ptr; } string;
struct { unsigned int length; struct json_object_entry_t * values; } object;
struct { unsigned int length; struct json_value_t ** values; } array;
} u;
/* `reserved` is used internally by the parser; do not access it from user code. */
};
struct json_object_entry_t {
char * name;
unsigned int name_length;
struct json_value_t * value;
};
API
struct json_value_t * json_parse(const char * json, size_t length, char * errbuf);
void json_free(struct json_value_t * value);
json_parse— Parse JSON text oflengthbytes into a tree ofjson_value_tnodes. Returns the root on success,NULLon failure.errbufreceives the error message; it may beNULLif not needed, otherwise the caller must provide at least 256 bytes. Error messages are of the formline 12: Unexpected ',' in object(line number only).json_free— Free the entire parse tree. Implemented iteratively, so deeply nested JSON will not blow the C stack.
Example
char errbuf[256];
const char * text = "{\"name\":\"xstar\",\"version\":1}";
struct json_value_t * root = json_parse(text, strlen(text), errbuf);
if(root && root->type == JSON_OBJECT)
{
for(unsigned int i = 0; i < root->u.object.length; i++)
{
struct json_object_entry_t * entry = &root->u.object.values[i];
if(entry->value->type == JSON_STRING)
printf("%s = %s\n", entry->name, entry->value->u.string.ptr);
else if(entry->value->type == JSON_INTEGER)
printf("%s = %lld\n", entry->name, (long long)entry->value->u.integer);
}
}
else if(!root)
{
printf("parse error: %s\n", errbuf);
}
json_free(root);