Parser
Build an in-memory tree.
Structures π
- struct judo_error
Parse error.
Lifecycle functions π
Construct and destroy an in-memory tree.
- enum judo_resultconst char *source, int32_t length, judo_value **root, struct judo_error *error, void *user_data, judo_memfunc memfunc)
Build an in-memory tree.
Free the in-memory tree.
Value functions π
Inspect JSON values from the in-memory tree.
Type of a JSON value.
Boolean value.
Array or object length.
First array element.
Next array element.
First object member.
Next object member.
Member value.
Value lexeme.
Member name lexeme.
Types π
- typedef struct judo_value judo_value
JSON value.
- typedef struct judo_member judo_member
Object member.
- typedef void *(*judo_memfunc)(void *user_data, void *ptr, size_t size)
Memory manager.
Enumerations π
- enum judo_type
JSON value type.
Discussion π
The Judo parser builds an in-memory tree structure from JSON source text. The βrootβ of the tree is the top-level JSON value, which is often an object or array. From the root, you can traverse the tree and inspect its values.
The judo_parse function parses JSON source text, encoded as UTF-8, into a tree. The source text can be null or non-null terminated. In the subsequent example, it is null terminated which is communicated by passing -1
to the functions length
parameter.
Once the tree has been processed, you must free it with judo_free.
const char *json = "{\"abc\":123}";
struct judo_value *root = NULL;
enum judo_result result = judo_parse(json, -1, &root, NULL, NULL, memfunc);
if (result == JUDO_SUCCESS) {
// Process the tree here, then
// free it once you're done.
judo_free(root, NULL, memfunc);
}
The Judo parser requires a dynamic memory allocator, which you must implement yourself. The previous code snippet used memfunc
to refer to the implied memory allocator function.
Handling Errors π
If an error occurs, then judo_parse will return an error code (a result code other than JUDO_SUCCESS). The result code indicates the general classification of the error, e.g. syntax error, bad encoding, etc. Regardless of the error code, the judo_error argument, if provided, will be populated with details about the error.
Processing the In-Memory Tree π
The type of the JSON root, as well as every other value in the tree, is represented by the opaque type judo_value. You can inspect the type with the judo_gettype function. For example, if a value represents the JSON null
type, then judo_gettype with return JUDO_TYPE_NULL.
In JSON, the null
type is a simple type. That is, there is no additional information associated with it. However, other JSON types (e.g. arrays and objects), do have additional data. For example, arrays have elements and objects have members associated with them. Inspecting these values is explored in the following subsections.
Boolean Values π
If a value represents a boolean type, then judo_gettype will return JUDO_TYPE_BOOL. Once you know a value is a boolean type, you can use judo_tobool to determine whether it is true
or false
.
if (judo_gettype(root) == JUDO_TYPE_BOOL) {
if (judo_tobool(root)) {
// 'true'
} else {
// 'false'
}
}
Numeric Values π
If a value represents a number type, then judo_gettype will return JUDO_TYPE_NUMBER. You can query the lexeme of the number with the judo_value2span function. Once you have the lexeme, you can use judo_numberify to convert it into a floating-point value.
if (judo_gettype(root) == JUDO_TYPE_NUMBER) {
struct judo_span lexeme = judo_value2span(root);
// Use the lexeme span to extract the float value.
}
String Values π
If a value represents a string type, then judo_gettype will return JUDO_TYPE_STRING. You can query the lexeme of the string with the judo_value2span function. Once you have the lexeme, you can use judo_stringify to decode it.
if (judo_gettype(root) == JUDO_TYPE_STRING) {
struct judo_span lexeme = judo_value2span(root);
// Use the lexeme span to extract the float value.
}
Array Values π
If a value represents an array type, then judo_gettype will return JUDO_TYPE_ARRAY. You can iterate the elements of an array with the judo_first and judo_next functions.
The judo_first function returns the first element of the array. If the array is empty, then it will return NULL. You can call judo_next on any array element to retrieve the next element. If judo_next returns NULL, then there are no more elements.
if (judo_gettype(root) == JUDO_TYPE_ARRAY) {
struct judo_value *element = judo_first(root);
while (element != NULL) {
// Process the current element, then
// grab to the next element.
element = judo_next(element);
}
}
You can query how many elements are in an array with judo_len.
Object Values π
If a value represents an object type, then judo_gettype will return JUDO_TYPE_OBJECT. You can iterate the members of an object with the judo_membfirst and judo_membnext functions.
The judo_membfirst function returns the first member of the object. If the object has no members, then it will return NULL. You can call judo_membnext on any object member to retrieve the next member. If judo_membnext returns NULL, then there are no more members.
if (judo_gettype(root) == JUDO_TYPE_OBJECT) {
struct judo_member *member = judo_membfirst(root);
while (member != NULL) {
// Process the current member, then
// grab to the next member.
member = judo_membnext(member);
}
}
You can query how many members are in an object with judo_len.
You can retrieve the name and value of a member with the judo_name2span and judo_membvalue functions, respectively.
The JSON specification does not require member names to be unique. Therefore, Judo allows multiple members with the same name within a single object. If this behavior is undesirable, application developers should detect and handle duplicates accordingly