JSON

Mongoose library is often used to exchange data in JSON format, therefore we have provided utility functions to format JSON strings easily:

mg_http_reply(c, 200, "Content-Type: application/json\r\n",
              "{%m: %u}", MG_ESC("value"), 123);  // {"value": 123}

Therefore, for full JSON support, a set of parsing functions is required - which is described below.

mg_json_get()

enum { MG_JSON_TOO_DEEP = -1, MG_JSON_INVALID = -2, MG_JSON_NOT_FOUND = -3 };
int mg_json_get(struct mg_str json, const char *path, int *toklen);

Parse JSON string json and return the offset of the element specified by the JSON path. The length of the element is stored in the toklen.

Parameters:

  • json - a string containing valid JSON
  • path - a JSON path. Must start with $, e.g. $.user
  • toklen - a pointer that receives element's length, can be NULL

Return value: offset of the element, or negative MG_JSON_* on error.

Usage example:

// Create a json string: { "a": 1, "b": [2, 3] }
char *buf = mg_mprintf("{ %m: %d, %m: [%d, %d] }",
                       MG_ESC("a"), 1,
                       MG_ESC("b"), 2, 3);
struct mg_str json = mg_str(buf);
int offset, length;

// Lookup "$", which is the whole JSON. Can be used for validation
offset = mg_json_get(json, "$", &length);    // offset = 0, length = 23

// Lookup attribute "a". Point to value "1"
offset = mg_json_get(json, "$.a", &length);  // offset = 7, length = 1

// Lookup attribute "b". Point to array [2, 3]
offset = mg_json_get(json, "$.b", &length);  // offset = 15, length = 6

// Lookup attribute "b[1]". Point to value "3"
offset = mg_json_get(json, "$.b[1]", &length); // offset = 19, length = 1

mg_free(buf);

mg_json_get_tok()

struct mg_str mg_json_get_tok(struct mg_str json, const char *path);

Parse JSON string json and return a struct mg_str pointing to the value of the element specified by the JSON path. Useful to check if a token is present, or inspect when it can have different types.

Parameters:

  • json - a string containing valid JSON
  • path - a JSON path. Must start with $, e.g. $.user

Return value: a struct mg_str pointing to the value of the element, or with a NULL pointer on error.

Usage example:

  json = mg_str("{\"a\":\"b:c\"}");
  val = mg_json_get_tok(json, "$.a"); // "b:c"

mg_json_get_num()

bool mg_json_get_num(struct mg_str json, const char *path, double *v);

Fetch numeric (double) value from the json string json at JSON path path into a placeholder v. Return true if successful.

Parameters:

  • json - a string containing valid JSON
  • path - a JSON path. Must start with $
  • v - a placeholder for value

Return value: true on success, false on error

Usage example:

double d = 0.0;
mg_json_get_num(mg_str("[1,2,3]", "$[1]", &d));     // d == 2
mg_json_get_num(mg_str("{\"a\":1.23}", "$.a", &d)); // d == 1.23

mg_json_get_bool()

bool mg_json_get_bool(struct mg_str json, const char *path, bool *v);

Fetch boolean (bool) value from the json string json at JSON path path into a placeholder v. Return true if successful.

Parameters:

  • json - a string containing valid JSON
  • path - a JSON path. Must start with $
  • v - a placeholder for value

Return value: true on success, false on error

Usage example:

bool b = false;
mg_json_get_bool(mg_str("[123]", "$[0]", &b));   // Error. b remains to be false
mg_json_get_bool(mg_str("[true]", "$[0]", &b));  // b is true

mg_json_get_long()

long mg_json_get_long(struct mg_str json, const char *path, long default_val);

Fetch integer numeric (long) value from the json string json at JSON path path. Return it if found, or default_val if not found.

Parameters:

  • json - a string containing valid JSON
  • path - a JSON path. Must start with $
  • default_val - a default value for the failure case

Return value: found value, or default_val value

Usage example:

long a = mg_json_get_long(mg_str("[123]", "$a", -1));   // a = -1
long b = mg_json_get_long(mg_str("[123]", "$[0]", -1)); // b = 123

mg_json_get_str()

char *mg_json_get_str(struct mg_str json, const char *path);

Fetch string value from the json string json at JSON path path. If found, a string is allocated using mg_calloc(), un-escaped, and returned to the caller. It is the caller's responsibility to mg_free() the returned string.

Parameters:

  • json - a string containing valid JSON
  • path - a JSON path. Must start with $

Return value: non-NULL on success, NULL on error

Usage example:

struct mg_str json = mg_str("{\"a\": \"hi\"}");  // json = {"a": "hi"}
char *str = mg_json_get_str(json, "$.a");        // str = "hi"
mg_free(str);

mg_json_get_hex()

char *mg_json_get_hex(struct mg_str json, const char *path, int *len);

Fetch hex-encoded buffer from the json string json at JSON path path. If found, a buffer is allocated using mg_calloc(), decoded, and returned to the caller. It is the caller's responsibility to mg_free() the returned string. Returned buffer is nul-terminated.

Parameters:

  • json - a string containing valid JSON
  • path - a JSON path. Must start with $
  • len - a pointer that receives decoded length. Can be NULL

Return value: non-NULL on success, NULL on error

Usage example:

struct mg_str json = mg_str("{\"a\": \"6869\"}"); // json = {"a": "6869"}
char *str = mg_json_get_hex(json, "$.a", NULL);   // str = "hi"
mg_free(str);

mg_json_get_b64()

char *mg_json_get_b4(struct mg_str json, const char *path, int *len);

Fetch base64-encoded buffer from the json string json at JSON path path. If found, a buffer is allocated using mg_calloc(), decoded, and returned to the caller. It is the caller's responsibility to mg_free() the returned string. Returned buffer is nul-terminated.

Parameters:

  • json - a string containing valid JSON
  • path - a JSON path. Must start with $
  • len - a pointer that receives decoded length. Can be NULL

Return value: non-NULL on success, NULL on error

Usage example:

struct mg_str json = mg_str("{\"a\": \"YWJj\"}"); // json = {"a": "YWJj"}
char *str = mg_json_get_b64(json, "$.a", NULL);   // str = "abc"
mg_free(str);

mg_json_unescape()

bool mg_json_unescape(struct mg_str str, char *buf, size_t len);

Unescape a JSON string

Parameters:

  • str - a string containing valid JSON to be unescaped
  • buf - buffer where to place the result
  • len - buffer length

Return value: true on success, false on error

Usage example:

struct mg_str str = mg_str("{\"a\": \"b\\u0063d\"}"); // escaped json = {"a": "b\u0063d"}
char json[20];
bool result = mg_json_unescape(str, result, 20);    // json = {"a": "bcd"}

mg_json_next()

size_t mg_json_next(struct mg_str obj, size_t ofs, struct mg_str *key, struct mg_str *val);

Iterate over elements of an object or array. An initial value for ofs must be 0, then on each iteration a previously returned value should be passed.

Parameters:

  • json - a string containing valid JSON
  • ofs - an offset of the element
  • key - a pointer that receives key. For arrays, set to empty. Can be NULL
  • val - a pointer that receives value. Can be NULL

Return value: non-0 on success, 0 when there are no more elements

Usage example:

struct mg_str key, val, obj = mg_str("{\"a\": [true], \"b\": 12345}");
size_t ofs = 0;
while ((ofs = mg_json_next(obj, ofs, &key, &val)) > 0) {
  printf("%.*s -> %.*s\n", (int) key.len, key.buf, (int) val.len, val.buf);
}

For an example on how to iterate over an arbitrary JSON string, see json_scan() function in the unit test.