mu_json
is a compact, efficient JSON parser designed with embedded systems
in mind.
mu_json
's features include:
- Written in pure C
- Conforms to IETF RFC-7159
- No calls to
malloc()
orfree()
- In-place, copy-free parsing of JSON strings
- Provides functions to traverse parsed JSON tree (parent, child, sibling)
- Includes
mu_str
module for safe copy-free string processing
mu_json
takes a JSON formatted string and parses it into its constituent
tokens. Once parsed, mu_json
provides functions to navigate among the
resulting tokens via parent, child, next_sibling, prev_sibling, etc.
in place: Unlike many parsers, mu_json
does not try to interpret the
parsed values. Rather, it simply slices each token into a substring and
associates a JSON type to it (ARRAY, OBJECT, NUMBER, TRUE, FALSE, NULL) and the
token's depth in the parsed tree.
malloc-free: The caller provies token storage, so mu_json never calls malloc() or free().
Douglas Crockford for creating JSON in the first place, and for the compact JSON_checker.c design on which much of mu_json is based.
Serge Zaitsev for creating jsmn, an efficient
copy-free JSON parser, which inspired the "sliced token" approach used by
mu_json
.
Nicolas Seriot for creating the comprehensive
JSONTestSuite, used as a basis for the
mu_json
unit tests.
#include "mu_json.h"
#include "mu_str.h"
#include <stdio.h>
// Helper functions
const char *token_type_string(mu_json_token_t *t) {
switch (mu_json_token_type(t)) {
case MU_JSON_TOKEN_TYPE_UNKNOWN: return "UNKNOWN";
case MU_JSON_TOKEN_TYPE_ARRAY: return "ARRAY";
case MU_JSON_TOKEN_TYPE_OBJECT: return "OBJECT";
case MU_JSON_TOKEN_TYPE_STRING: return "STRING";
case MU_JSON_TOKEN_TYPE_NUMBER: return "NUMBER";
case MU_JSON_TOKEN_TYPE_INTEGER: return "INTEGER";
case MU_JSON_TOKEN_TYPE_TRUE: return "TRUE";
case MU_JSON_TOKEN_TYPE_FALSE: return "FALSE";
case MU_JSON_TOKEN_TYPE_NULL: return "NULL";
}
}
void print_token_slice(mu_json_token_t *t) {
mu_str_t *s = mu_json_token_slice(t);
printf("'%.*s'\n", (int)mu_str_length(s), mu_str_buf(s));
}
#define N_DEMO_TOKENS 10
int main() {
mu_json_token_t tokens[N_DEMO_TOKENS];
const char *json = " {\"a\":111, \"b\":[22.2, true], \"c\":{}} ";
int n_tokens = mu_json_parse_c_str(tokens, N_DEMO_TOKENS, json, NULL);
for (int i = 0; i < n_tokens; i++) {
mu_json_token_t *t = &tokens[i];
printf("token[%d]: %7s depth=%d, ", i, token_type_string(t),
mu_json_token_depth(t));
print_token_slice(t);
}
}
Compiling and running the above results in:
token[0]: OBJECT depth=0, '{"a":111, "b":[22.2, true], "c":{}}'
token[1]: STRING depth=1, '"a"'
token[2]: INTEGER depth=1, '111'
token[3]: STRING depth=1, '"b"'
token[4]: ARRAY depth=1, '[22.2, true]'
token[5]: NUMBER depth=2, '22.2'
token[6]: TRUE depth=2, 'true'
token[7]: STRING depth=1, '"c"'
token[8]: OBJECT depth=1, '{}'