Parser

Build an in-memory tree.

Structures πŸ”—

struct judo_error

Parse error.

Lifecycle functions πŸ”—

Construct and destroy an in-memory tree.

const char *source, int32_t length, judo_value **root, struct judo_error *error, void *user_data, judo_memfunc memfunc)

Build an in-memory tree.

judo_value *root, void *user_data, judo_memfunc memfunc)

Free the in-memory tree.

Value functions πŸ”—

Inspect JSON values from the in-memory tree.

enum judo_type 
const judo_value *value)

Type of a JSON value.

bool 
judo_value *value)

Boolean value.

int32_t 
const judo_value *value)

Array or object length.

First array element.

Next array element.

First object member.

Next object member.

Member value.

struct judo_span 
const judo_value *value)

Value lexeme.

struct judo_span 
const judo_member *member)

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