JSON parser and generator for C/C++ with scanf/printf like interface. Targeting embedded systems.

Related tags

JSON frozen
Overview

JSON parser and emitter for C/C++

Features

  • ISO C and ISO C++ compliant portable code
  • Very small footprint
  • No dependencies
  • json_scanf() scans a string directly into C/C++ variables
  • json_printf() prints C/C++ variables directly into an output stream
  • json_setf() modifies an existing JSON string
  • json_fread() reads JSON from a file
  • json_fprintf() writes JSON to a file
  • Built-in base64 encoder and decoder for binary data
  • Parser provides low-level callback API and high-level scanf-like API
  • 100% test coverage
  • Used in Mongoose OS, an operating system for connected commercial products on low-power microcontrollers

API reference

json_scanf(), json_vscanf

int json_scanf(const char *str, int str_len, const char *fmt, ...);
int json_vscanf(const char *str, int str_len, const char *fmt, va_list ap);

/* json_scanf's %M handler  */
typedef void (*json_scanner_t)(const char *str, int len, void *user_data);

Scans the JSON string str, performing scanf-like conversions according to fmt. fmt uses scanf()-like format, with the following differences:

  1. Object keys in the format string don't have to be quoted, e.g. "{key: %d}"
  2. Order of keys in the format string does not matter, and the format string may omit keys to fetch only those that are of interest, for example, assume str is a JSON string { "a": 123, "b": "hi", c: true }. We can fetch only the value of the c key:
    int value = 0;
    json_scanf(str, strlen(str), "{c: %B}", &value);
  3. Several extra format specifiers are supported:
    • %B: consumes int * (or char *, if sizeof(bool) == sizeof(char)), expects boolean true or false.
    • %Q: consumes char **, expects quoted, JSON-encoded string. Scanned string is malloc-ed, caller must free() the string.
    • %V: consumes char **, int *. Expects base64-encoded string. Result string is base64-decoded, malloced and NUL-terminated. The length of result string is stored in int * placeholder. Caller must free() the result.
    • %H: consumes int *, char **. Expects a hex-encoded string, e.g. "fa014f". Result string is hex-decoded, malloced and NUL-terminated. The length of the result string is stored in int * placeholder. Caller must free() the result.
    • %M: consumes custom scanning function pointer and void *user_data parameter - see json_scanner_t definition.
    • %T: consumes struct json_token *, fills it out with matched token.

Returns the number of elements successfully scanned & converted. Negative number means scan error.

Example - scan arbitrary JSON string:

  // str has the following JSON string (notice keys are out of order):
  // { "a": 123, "d": true, "b": [1, 2], "c": "hi" }

  int a = 0, d = 0;
  char *c = NULL;
  void *my_data = NULL;
  json_scanf(str, strlen(str), "{ a:%d, b:%M, c:%Q, d:%B }",
             &a, scan_array, my_data, &c, &d);

  // This function is called by json_scanf() call above.
  // str is "[1, 2]", user_data is my_data.
  static void scan_array(const char *str, int len, void *user_data) {
    struct json_token t;
    int i;
    printf("Parsing array: %.*s\n", len, str);
    for (i = 0; json_scanf_array_elem(str, len, "", i, &t) > 0; i++) {
      printf("Index %d, token [%.*s]\n", i, t.len, t.ptr);
    }
  }

Example - parse array of objects:

  // str has the following JSON string - array of objects:
  // { "a": [ {"b": 123}, {"b": 345} ] }
  // This example shows how to iterate over array, and parse each object.

  int i, value, len = strlen(str);
  struct json_token t;

  for (i = 0; json_scanf_array_elem(str, len, ".a", i, &t) > 0; i++) {
    // t.type == JSON_TYPE_OBJECT
    json_scanf(t.ptr, t.len, "{b: %d}", &value);  // value is 123, then 345
  }

json_scanf_array_elem()

int json_scanf_array_elem(const char *s, int len,
                          const char *path,
                          int index,
                          struct json_token *token);

A helper function to scan an array item with given path and index. Fills token with the matched JSON token. Returns -1 if no array element found, otherwise non-negative token length.

json_printf()

Frozen printing API is pluggable. Out of the box, Frozen provides a way to print to a string buffer or to an opened file stream. It is easy to tell Frozen to print to another destination, for example, to a socket, etc. Frozen does this by defining an "output context" descriptor which has a pointer to a low-level printing function. If you want to print to another destination, just define your specific printing function and initialise output context with it.

This is the definition of the output context descriptor:

struct json_out {
  int (*printer)(struct json_out *, const char *str, size_t len);
  union {
    struct {
      char *buf;
      size_t size;
      size_t len;
    } buf;
    void *data;
    FILE *fp;
  } u;
};

Frozen provides two helper macros to initialise two built-in output descriptors:

struct json_out out1 = JSON_OUT_BUF(buf, len);
struct json_out out2 = JSON_OUT_FILE(fp);
typedef int (*json_printf_callback_t)(struct json_out *, va_list *ap);
int json_printf(struct json_out *, const char *fmt, ...);
int json_vprintf(struct json_out *, const char *fmt, va_list ap);

Generate formatted output into a given string buffer, auto-escaping keys. This is a superset of printf() function, with extra format specifiers:

  • %B print json boolean, true or false. Accepts an int.
  • %Q print quoted escaped string or null. Accepts a const char *.
  • %.*Q same as %Q, but with length. Accepts int, const char *
  • %V print quoted base64-encoded string. Accepts a const char *, int.
  • %H print quoted hex-encoded string. Accepts a int, const char *.
  • %M invokes a json_printf_callback_t function. That callback function can consume more parameters.

Return number of bytes printed. If the return value is bigger than the supplied buffer, that is an indicator of overflow. In the overflow case, overflown bytes are not printed.

Example:

  json_printf(&out, "{%Q: %d, x: [%B, %B], y: %Q}", "foo", 123, 0, -1, "hi");
  // Result:
  // {"foo": 123, "x": [false, true], "y": "hi"}

To print a complex object (for example, serialise a structure into an object), use %M format specifier:

  struct my_struct { int a, b; } mys = {1,2};
  json_printf(&out, "{foo: %M, bar: %d}", print_my_struct, &mys, 3);
  // Result:
  // {"foo": {"a": 1, "b": 2}, "bar": 3}
int print_my_struct(struct json_out *out, va_list *ap) {
  struct my_struct *p = va_arg(*ap, struct my_struct *);
  return json_printf(out, "{a: %d, b: %d}", p->a, p->b);
}

json_printf_array()

int json_printf_array(struct json_out *, va_list *ap);

A helper %M callback that prints contiguous C arrays. Consumes void *array_ptr, size_t array_size, size_t elem_size, char *fmt Returns number of bytes printed.

json_walk() - low level parsing API

/* JSON token type */
enum json_token_type {
  JSON_TYPE_INVALID = 0, /* memsetting to 0 should create INVALID value */
  JSON_TYPE_STRING,
  JSON_TYPE_NUMBER,
  JSON_TYPE_TRUE,
  JSON_TYPE_FALSE,
  JSON_TYPE_NULL,
  JSON_TYPE_OBJECT_START,
  JSON_TYPE_OBJECT_END,
  JSON_TYPE_ARRAY_START,
  JSON_TYPE_ARRAY_END,

  JSON_TYPES_CNT,
};

/*
 * Structure containing token type and value. Used in `json_walk()` and
 * `json_scanf()` with the format specifier `%T`.
 */
struct json_token {
  const char *ptr;           /* Points to the beginning of the value */
  int len;                   /* Value length */
  enum json_token_type type; /* Type of the token, possible values are above */
};

/* Callback-based API */
typedef void (*json_walk_callback_t)(void *callback_data,
                                     const char *name, size_t name_len,
                                     const char *path,
                                     const struct json_token *token);

/*
 * Parse `json_string`, invoking `callback` in a way similar to SAX parsers;
 * see `json_walk_callback_t`.
 */
int json_walk(const char *json_string, int json_string_length,
              json_walk_callback_t callback, void *callback_data);

json_walk() is a low-level, callback based parsing API. json_walk() calls a given callback function for each scanned value.

Callback receives a name, a path to the value, a JSON token that points to the value and an arbitrary user data pointer.

The path is constructed using this rule:

  • Root element has "" (empty string) path
  • When an object starts, . (dot) is appended to the path
  • When an object key is parsed, a key name is appended to the path
  • When an array is parsed, an [ELEMENT_INDEX] is appended for each element

For example, consider the following json string: { "foo": 123, "bar": [ 1, 2, { "baz": true } ] }. The sequence of callback invocations will be as follows:

  • type: JSON_TYPE_OBJECT_START, name: NULL, path: "", value: NULL
  • type: JSON_TYPE_NUMBER, name: "foo", path: ".foo", value: "123"
  • type: JSON_TYPE_ARRAY_START, name: "bar", path: ".bar", value: NULL
  • type: JSON_TYPE_NUMBER, name: "0", path: ".bar[0]", value: "1"
  • type: JSON_TYPE_NUMBER, name: "1", path: ".bar[1]", value: "2"
  • type: JSON_TYPE_OBJECT_START, name: "2", path: ".bar[2]", value: NULL
  • type: JSON_TYPE_TRUE, name: "baz", path: ".bar[2].baz", value: "true"
  • type: JSON_TYPE_OBJECT_END, name: NULL, path: ".bar[2]", value: "{ \"baz\": true }"
  • type: JSON_TYPE_ARRAY_END, name: NULL, path: ".bar", value: "[ 1, 2, { \"baz\": true } ]"
  • type: JSON_TYPE_OBJECT_END, name: NULL, path: "", value: "{ \"foo\": 123, \"bar\": [ 1, 2, { \"baz\": true } ] }"

If top-level element is an array: [1, {"foo": 2}]

  • type: JSON_TYPE_ARRAY_START, name: NULL, path: "", value: NULL
  • type: JSON_TYPE_NUMBER, name: "0", path: "[0]", value: "1"
  • type: JSON_TYPE_OBJECT_START, name: "1", path: "[1]", value: NULL
  • type: JSON_TYPE_NUMBER, name: "foo", path: "[1].foo", value: "2"
  • type: JSON_TYPE_OBJECT_END, name: NULL, path: "[1]", value: "{\"foo\": 2}"
  • type: JSON_TYPE_ARRAY_END, name: NULL, path: "", value: "[1, {"foo": 2}]"

If top-level element is a scalar: true

  • type: JSON_TYPE_TRUE, name: NULL, path: "", value: "true"

json_fprintf(), json_vfprintf()

/*
 * Same as json_printf, but prints to a file.
 * File is created if does not exist. File is truncated if already exists.
 */
int json_fprintf(const char *file_name, const char *fmt, ...);
int json_vfprintf(const char *file_name, const char *fmt, va_list ap);

json_asprintf(), json_vasprintf()

/*
 * Print JSON into an allocated 0-terminated string.
 * Return allocated string, or NULL on error.
 * Example:
 *
 * ```c
 *   char *str = json_asprintf("{a:%H}", 3, "abc");
 *   printf("%s\n", str);  // Prints "616263"
 *   free(str);
 * ```
 */
char *json_asprintf(const char *fmt, ...);
char *json_vasprintf(const char *fmt, va_list ap);

json_fread()

/*
 * Read the whole file in memory.
 * Return malloc-ed file content, or NULL on error. The caller must free().
 */
char *json_fread(const char *file_name);

json_setf(), json_vsetf()

/*
 * Update given JSON string `s,len` by changing the value at given `json_path`.
 * The result is saved to `out`. If `json_fmt` == NULL, that deletes the key.
 * If path is not present, missing keys are added. Array path without an
 * index pushes a value to the end of an array.
 * Return 1 if the string was changed, 0 otherwise.
 *
 * Example:  s is a JSON string { "a": 1, "b": [ 2 ] }
 *   json_setf(s, len, out, ".a", "7");     // { "a": 7, "b": [ 2 ] }
 *   json_setf(s, len, out, ".b", "7");     // { "a": 1, "b": 7 }
 *   json_setf(s, len, out, ".b[]", "7");   // { "a": 1, "b": [ 2,7 ] }
 *   json_setf(s, len, out, ".b", NULL);    // { "a": 1 }
 */
int json_setf(const char *s, int len, struct json_out *out,
              const char *json_path, const char *json_fmt, ...);

int json_vsetf(const char *s, int len, struct json_out *out,
               const char *json_path, const char *json_fmt, va_list ap);

json_prettify()

/*
 * Pretty-print JSON string `s,len` into `out`.
 * Return number of processed bytes in `s`.
 */
int json_prettify(const char *s, int len, struct json_out *out);

json_prettify_file()

/*
 * Prettify JSON file `file_name`.
 * Return number of processed bytes, or negative number of error.
 * On error, file content is not modified.
 */
int json_prettify_file(const char *file_name);

json_next_key(), json_next_elem()

/*
 * Iterate over an object at given JSON `path`.
 * On each iteration, fill the `key` and `val` tokens. It is OK to pass NULL
 * for `key`, or `val`, in which case they won't be populated.
 * Return an opaque value suitable for the next iteration, or NULL when done.
 *
 * Example:
 *
 * ```c
 * void *h = NULL;
 * struct json_token key, val;
 * while ((h = json_next_key(s, len, h, ".foo", &key, &val)) != NULL) {
 *   printf("[%.*s] -> [%.*s]\n", key.len, key.ptr, val.len, val.ptr);
 * }
 * ```
 */
void *json_next_key(const char *s, int len, void *handle, const char *path,
                    struct json_token *key, struct json_token *val);


/*
 * Iterate over an array at given JSON `path`.
 * Similar to `json_next_key`, but fills array index `idx` instead of `key`.
 */
void *json_next_elem(const char *s, int len, void *handle, const char *path,
                     int *idx, struct json_token *val);

Minimal mode

By building with -DJSON_MINIMAL=1 footprint can be significantly reduced. The following limitations apply in this configuration:

  • Only integer numbers are supported. This affects parsing and %f/%lf conversions in printf and scanf.
  • Hex ('%H') and base64 (%V) conversions are disabled.

Examples

Print JSON configuration to a file

json_fprintf("settings.json", "{ a: %d, b: %Q }", 123, "string_value");
json_prettify_file("settings.json"); // Optional

Read JSON configuration from a file

struct my_config { int a; char *b; } c = { .a = 0, .b = NULL };
char *content = json_fread("settings.json");
json_scanf(content, strlen(content), "{a: %d, b: %Q}", &c.a, &c.b);

Modify configuration setting in a JSON file

const char *settings_file_name = "settings.json", *tmp_file_name = "tmp.json";
char *content = json_fread(settings_file_name);
FILE *fp = fopen(tmp_file_name, "w");
struct json_out out = JSON_OUT_FILE(fp);
json_setf(content, strlen(content), &out, ".b", "%Q", "new_string_value");
fclose(fp);
json_prettify_file(tmp_file_name);  // Optional
rename(tmp_file_name, settings_file_name);

Contributions

To submit contributions, sign Cesanta CLA and send GitHub pull request.

Licensing

Frozen is released under the Apache 2.0 license.

For commercial support and professional services, contact us.

Comments
  • Supporting arrarys and _ character

    Supporting arrarys and _ character

    Hi, hope you would be doing great.

    Consider following code from main.c from you code files, I've just replaced the static string json with mine. Issue is if string is starting with [ (square brace), function execution ends at parse_json line. I wanted to asked does you code supports json starting with square brackets, i.e., arrays. Also, does its support underscore (_) in keys, e.g., when i replace 'id' with '_id' it give me same behavior as described above.

    static const char *test_nested(void) { struct json_token ar[100]; const char *s = "[{"id":123,"bookmark":1,"date":430654481,"title":"Welcome to IE7","url":"http://go.microsoft.com/fwlink/?linkid=68919","visits":1}]"; enum json_type types[] = {JSON_TYPE_OBJECT, JSON_TYPE_STRING, JSON_TYPE_ARRAY, JSON_TYPE_OBJECT, JSON_TYPE_STRING, JSON_TYPE_NUMBER, JSON_TYPE_STRING, JSON_TYPE_NUMBER, JSON_TYPE_STRING, JSON_TYPE_NUMBER, JSON_TYPE_STRING, JSON_TYPE_STRING, JSON_TYPE_STRING, JSON_TYPE_STRING, JSON_TYPE_STRING, JSON_TYPE_NUMBER, JSON_TYPE_EOF }; int i, ar_size = ARRAY_SIZE(ar), types_size = ARRAY_SIZE(types);

    ASSERT(parse_json(s, strlen(s), ar, ar_size) == (int) strlen(s));
    for (i = 0; i < types_size; i++) {
        ASSERT(ar[i].type == types[i]);
    }
    ASSERT(find_json_token(ar, "a[0]") == &ar[3]);
    ASSERT(find_json_token(ar, "a[0][0]") == &ar[4]);
    ASSERT(find_json_token(ar, "a[0][1]") == &ar[5]);
    ASSERT(find_json_token(ar, "a[0][2]") == &ar[6]);
    ASSERT(find_json_token(ar, "a[0][2].b") == &ar[8]);
    
    return NULL;
    

    }

    Any help will be appreciated. Thanks in advance.

    Cheers. :)

    opened by waleedmahmood 7
  • Issue in json_setf

    Issue in json_setf

    Hi,

    I want to manipulate json data for example "{ "a": 123, "b": [ 1 ], "c": true }" // this is taken from your unit_test.c file

    Want to change "a" value to 7 json_setf(szJSON, strlen(szJSON), &out, ".a", "%d", 7);

    I am getting following output { "a": 7, "b": [ 1 ], "c": t

    Last 5 characters get truncated.

    Could you please look into this issue. Note: above string works if we remove SPACE after COMMA and SPACE inside the ARRAY

    Here is my code:

    void main() { char *szJSON = "{ "a": 123, "b": [ 1 ], "c": true }"; char buf[1024]; struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));

    memset(buf, 0, 1024);
    json_setf(szJSON, strlen(szJSON), &out, ".a", "%d", 7);
    printf("%s\n\n", buf);
    
    getch();
    

    }

    opened by wahab80 4
  • JSON array as a valid first input not only object.

    JSON array as a valid first input not only object.

    Allow to parse JSON which starts with an array that is, first character in JSON data is '['.

    Example : [80, 443, {x: 25} ] Access the 'x' value using path [2].x

    opened by w-vi 4
  • fix

    fix "%g" and "%e" in json_printf and json_printf_array

    • json_printf_array() only recognised "%f" as requiring a double argument; add 'e' and 'g' to the list and use strpbrk() to recognise them all
    • when delegating to system printf, json_vprintf() didn't expect "eE" to end format specifiers; add them to the list
    • add new unit tests utilizing "%g" and "%e" formats in json_printf_array()
    opened by aitap 3
  • Parsing string from a JSON object

    Parsing string from a JSON object

    Hi,

    Thanks for your work on this parser, this is the first time i work with JSON and frozen has been very helpful.

    I'm able to parse ints and booleans from the JSON object str but i haven't been able to parse the string value from the key b. Here's the code i'm using:

    #include <string.h>
    #include <stdlib.h>
    #include "frozen.h"
    
    int main(void)
    {
    
    const char *header = "JSON: ";
    const char *val_a = "Valor del key a: ";
    const char *val_b = "Valor del key b: ";
    const char *val_c = "Valor del key c: ";
    
    // JSON Object
    const char *str= "{ \"a\": 123, \"b\": \"hi\", \"c\": true }";
    
    // Holders for the values
    int value_c = 0;
    int value_a = 0;
    char value_b[20];
    memset(value_b, '\0', sizeof(value_b));
    
    char msg_val[30];
    memset(msg_val, '\0', sizeof(msg_val));
    
    json_scanf(str, strlen(str), "{c:%B, a:%d}", &value_c, &value_a);
    int result = json_scanf(str, strlen(str), "{b: %Q}", value_b);
    
    HAL_UART_Transmit(&huart2, header, strlen(header), 500);
    HAL_UART_Transmit(&huart2, str, strlen(str), 500);
    HAL_UART_Transmit(&huart2, "\r\n", 2, 500);
    HAL_UART_Transmit(&huart2, val_a, strlen(val_a), 500);
    sprintf(msg_val, "%d\r\n", value_a);
    HAL_UART_Transmit(&huart2, msg_val, strlen(msg_val), 500);
    memset(msg_val, '\0', sizeof(msg_val));
    
    HAL_UART_Transmit(&huart2, val_b, strlen(val_b), 500);
    sprintf(msg_val, "result: %d, %s\r\n", result, value_b);
    HAL_UART_Transmit(&huart2, msg_val, strlen(msg_val), 500);
    
    HAL_UART_Transmit(&huart2, val_c, strlen(val_c), 500);
    sprintf(msg_val, "%s\r\n", value_c ? "true" : "false");
    HAL_UART_Transmit(&huart2, msg_val, strlen(msg_val), 500);
    memset(msg_val, '\0', sizeof(msg_val));
    
    free(value_b);
    
    while (1) {
    }
    
    }
    

    And this is the output i'm getting from the code above:

    JSON: { "a": 123, "b": "hi", "c": true } Valor del key a: 123 Valor del key b: result: 1, P Valor del key c: true

    I searched on here and the mongoose-os forum but haven't been able to solve my problem.

    Regards, Carlos

    opened by C47D 3
  • Makefile error

    Makefile error

    Hi,

    I'm trying to execute make but it keeps giving me the following error:

    screenshot from 2017-12-10 18-21-12

    What should I do to fix this? A fast reply would be highly appreciated,

    Thank you.

    opened by mutlucg 3
  • Stack based buffer overflow

    Stack based buffer overflow

    Hi,

    While I was auditing frozen library using PyJFuzz, I came across a stack based overflow using the following testcase with address sanitizer.

    e1f555ceb332dc1717778aba679cfdda20939edf.txt

    I didn't investigate further, anyway there're other exploitable issue, I'll report later.

    Thanks for your support! Regards, Daniele

    opened by dzonerzy 3
  • json_unescape(): Add basic UTF-8 support

    json_unescape(): Add basic UTF-8 support

    When calling a json_scanf() with a %Q format specifier unescaping of \u0020 to \u007F was added. Other unicodes in the format \uXXXX.. are bypassed directly to the result string. This way unescaping should be compliant with JSON RFC4627 Section 2.5 (Strings)

    opened by otg-abatec 2
  • Add support for

    Add support for "%ju" (uintmax_t) and "%jd" (intmax_t) in json_printf()

    Admittedly an incomplete PR, but would be nice to get these supported nonetheless. Parser side support is missing, and I haven't done any testing except on GCC & Linux.

    opened by toaarnio 2
  • Scan simple array doesn't work - {'b':[1,2]}

    Scan simple array doesn't work - {'b':[1,2]}

    Hi,

    My json looks something like this: "b : [1,2]", I couldn't extract it using json_scanf and callback.

    reproduce code (taken from the README.md):

    static void scan_array(const char *str, int len, void *user_data) { struct json_token t; int i; printf("Parsing array: %.*s\n", len, str); for (i = 0; json_scanf_array_elem(str, len, ".x", i, &t) > 0; i++) { printf("We are in the loop"); } }

    int a, b; char *c; void *my_data = NULL; char *str = "{ a: 123, d: true, b: [1, 2], c: hi }"; json_scanf(str, strlen(str), "{ a:%d, b:%M, c:%Q, d:%B }", &a, scan_array, my_data, &c, &b);

    It never get's in the loop... I assume the path shouldn't be ".x" but didn't find any documentation on what it should be (and empty string didn't work)

    Thanks!

    opened by yuvaljacoby 2
  • json_scanf does not interpret null string correctly

    json_scanf does not interpret null string correctly

    If a JSON object contains null property values, json_scanf with a %Q formatter converts these properties to a string containing the word "null" instead of a NULL string.

    For example, in the sample unit test below, I expect that result should be NULL, but instead it contains the string "null".

    { const char *str = "{a : null }"; char *result = NULL; ASSERT(json_scanf(str, strlen(str), "{a: %Q}", &result) == 0); ASSERT(result == NULL); free(result); }

    opened by jagoyette 2
  • Difference between MJSON and Frozen?

    Difference between MJSON and Frozen?

    Hello, cessanta hosts two JSON libraries: https://github.com/cesanta/mjson/ (~1.0 kLoC) https://github.com/cesanta/frozen/ (~1.5 kLoC)

    Both seem to be tiny. Is there any reccomendation on which library to use for specific use cases? I think it might be useful to cross-reference and mention this in READMEs of both libraries, so users can make better decisions when choosing between the two.

    Thanks.

    opened by Harvie 3
  • Lots of cppcheck warnings

    Lots of cppcheck warnings

    $ cppcheck --force .
    Checking frozen.c ...
    frozen.c:866:49: error: Pointer addition with NULL pointer. [nullPointerArithmetic]
      char *send = (char *) src + slen, *dend = dst + dlen, *orig_dst = dst, *p;
                                                    ^
    frozen.c:949:67: note: Calling function 'json_unescape', 3rd argument 'NULL' value is 0
            int unescaped_len = json_unescape(token->ptr, token->len, NULL, 0);
                                                                      ^
    frozen.c:866:49: note: Null pointer addition
      char *send = (char *) src + slen, *dend = dst + dlen, *orig_dst = dst, *p;
                                                    ^
    frozen.c:561:3: error: va_list 'ap' used before va_start() was called. [va_list_usedBeforeStarted]
      va_copy(ap, xap);
      ^
    frozen.c:572:30: error: va_list 'ap' used before va_start() was called. [va_list_usedBeforeStarted]
            int64_t val = va_arg(ap, int64_t);
                                 ^
    frozen.c:578:29: error: va_list 'ap' used before va_start() was called. [va_list_usedBeforeStarted]
            size_t val = va_arg(ap, size_t);
                                ^
    frozen.c:583:43: error: va_list 'ap' used before va_start() was called. [va_list_usedBeforeStarted]
            json_printf_callback_t f = va_arg(ap, json_printf_callback_t);
                                              ^
    frozen.c:584:24: error: va_list 'ap' used before va_start() was called. [va_list_usedBeforeStarted]
            len += f(out, &ap);
                           ^
    frozen.c:586:26: error: va_list 'ap' used before va_start() was called. [va_list_usedBeforeStarted]
            int val = va_arg(ap, int);
                             ^
    frozen.c:592:27: error: va_list 'ap' used before va_start() was called. [va_list_usedBeforeStarted]
            int i, n = va_arg(ap, int);
                              ^
    frozen.c:593:41: error: va_list 'ap' used before va_start() was called. [va_list_usedBeforeStarted]
            const unsigned char *p = va_arg(ap, const unsigned char *);
                                            ^
    frozen.c:603:41: error: va_list 'ap' used before va_start() was called. [va_list_usedBeforeStarted]
            const unsigned char *p = va_arg(ap, const unsigned char *);
                                            ^
    frozen.c:604:24: error: va_list 'ap' used before va_start() was called. [va_list_usedBeforeStarted]
            int n = va_arg(ap, int);
                           ^
    frozen.c:615:31: error: va_list 'ap' used before va_start() was called. [va_list_usedBeforeStarted]
              l = (size_t) va_arg(ap, int);
                                  ^
    frozen.c:618:20: error: va_list 'ap' used before va_start() was called. [va_list_usedBeforeStarted]
            p = va_arg(ap, char *);
                       ^
    frozen.c:652:9: error: va_list 'ap' used before va_start() was called. [va_list_usedBeforeStarted]
            va_copy(ap_copy, ap);
            ^
    frozen.c:676:13: error: va_list 'ap' used before va_start() was called. [va_list_usedBeforeStarted]
                va_copy(ap_copy, ap);
                ^
    frozen.c:696:25: error: va_list 'ap' used before va_start() was called. [va_list_usedBeforeStarted]
              (void) va_arg(ap, int64_t);
                            ^
    frozen.c:698:25: error: va_list 'ap' used before va_start() was called. [va_list_usedBeforeStarted]
              (void) va_arg(ap, int);
                            ^
    frozen.c:699:25: error: va_list 'ap' used before va_start() was called. [va_list_usedBeforeStarted]
              (void) va_arg(ap, char *);
                            ^
    frozen.c:704:29: error: va_list 'ap' used before va_start() was called. [va_list_usedBeforeStarted]
                  (void) va_arg(ap, int);
                                ^
    frozen.c:741:3: error: va_list 'ap' used before va_start() was called. [va_list_usedBeforeStarted]
      va_end(ap);
      ^
    frozen.c:652:9: error: va_list 'ap_copy' used before va_start() was called. [va_list_usedBeforeStarted]
            va_copy(ap_copy, ap);
            ^
    frozen.c:653:48: error: va_list 'ap_copy' used before va_start() was called. [va_list_usedBeforeStarted]
            need_len = vsnprintf(pbuf, size, fmt2, ap_copy);
                                                   ^
    frozen.c:654:9: error: va_list 'ap_copy' used before va_start() was called. [va_list_usedBeforeStarted]
            va_end(ap_copy);
            ^
    frozen.c:676:13: error: va_list 'ap_copy' used before va_start() was called. [va_list_usedBeforeStarted]
                va_copy(ap_copy, ap);
                ^
    frozen.c:677:49: error: va_list 'ap_copy' used before va_start() was called. [va_list_usedBeforeStarted]
                vsnprintf(pbuf, need_len + 1, fmt2, ap_copy);
                                                    ^
    frozen.c:678:13: error: va_list 'ap_copy' used before va_start() was called. [va_list_usedBeforeStarted]
                va_end(ap_copy);
                ^
    Checking frozen.c: JSON_ENABLE_BASE64...
    Checking frozen.c: JSON_ENABLE_HEX...
    Checking frozen.c: JSON_MINIMAL=0...
    Checking frozen.c: WEAK...
    Checking frozen.c: WEAK;_WIN32;__GNUC__;__TI_COMPILER_VERSION__...
    Checking frozen.c: _WIN32...
    Checking frozen.c: _WIN32;__GNUC__...
    1/2 files checked 56% done
    Checking unit_test.c ...
    frozen.c:812:28: error: Pointer addition with NULL pointer. [nullPointerArithmetic]
      frozen.end = json_string + json_string_length;
                               ^
    unit_test.c:122:3: note: Calling function 'json_walk', 1st argument 'NULL' value is 0
      ASSERT(json_walk(NULL, 0, NULL, 0) == JSON_STRING_INVALID);
      ^
    frozen.c:812:28: note: Null pointer addition
      frozen.end = json_string + json_string_length;
                               ^
    Checking unit_test.c: JSON_ENABLE_BASE64...
    Checking unit_test.c: JSON_ENABLE_HEX...
    Checking unit_test.c: JSON_MINIMAL=0...
    Checking unit_test.c: WEAK...
    Checking unit_test.c: WEAK;_WIN32;__GNUC__;__TI_COMPILER_VERSION__...
    Checking unit_test.c: _MSC_VER...
    Checking unit_test.c: _WIN32...
    Checking unit_test.c: _WIN32;__GNUC__...
    2/2 files checked 100% done
    
    opened by Harvie 0
  • frozen release with Apache License, Version 2.0

    frozen release with Apache License, Version 2.0

    Hello,

    frozen license had been changed to Apache License 2. Do you have plan to do a release under Apache License 2 in short term?

    Thank you very much.

    opened by mindongz 0
  • frozen 1.6 with Apache commons 2.0 dual licence

    frozen 1.6 with Apache commons 2.0 dual licence

    You recently switched to Apache commons 2.0 license for frozen.

    Can you create a 1.6-APL release under Apache commons 2.0 license as a fork from Tag 1.6? Or is there any GPL code in 1.6 so you are forced to have a GPL license?

    opened by arnehaber 4
  • Print array of structs to JSON (or nested/twodimensional array)

    Print array of structs to JSON (or nested/twodimensional array)

    Hello, i am trying to iterate over array of structs. There are 3 elements and i can iterate over it in for() { printf() } loops, but i can't get json_printf_array() to call custom struct handler for each element. Any ideas what is wrong with my code? Causes segfault.

    int print_my_struct(struct json_out *out, va_list *ap) {
      struct mgos_lib_info *p = va_arg(*ap, struct mgos_lib_info *);
      return json_printf(out, "{name: %s, version: %s}", p->name, p->version);
    }
    
    int main(void) {
    
    
    	printf("------------------\n");
    
    	for(size_t i = 0; i < (sizeof(mgos_libs_info) / sizeof(struct mgos_lib_info))-1; i++) {
    		printf("FHS DETECTED MODULE: %s version %s (init:%d)\n",
    			mgos_libs_info[i].name,
    			mgos_libs_info[i].version,
    			mgos_libs_info[i].init
    		);
    	}
    
    	printf("------------------\n");
    
    	for (const struct mgos_lib_info *l = mgos_libs_info; l->name != NULL; l++) {
    		printf("FHS DETECTED MODULE: %s version %s\n", l->name, l->version);
    	}
    
    	printf("------------------\n");
    
        char *json = json_asprintf("{modules:%M}",
                                   json_printf_array, mgos_libs_info, 3 * sizeof(mgos_libs_info[0]),
                                   sizeof(mgos_libs_info[0]), "%M", print_my_struct);
        if (json) {
            printf("%s\n", json);
            free(json);
        }
    
    }
    
    opened by Harvie 1
Releases(1.6)
  • 1.6(Jan 16, 2017)

    Changes

    • Added streaming/sax parsing support, json_walk()
    • Added C/C++ convenience API json_printf() and json_scanf(), which makes Frozen a unique choice for C/C++ as it allows to parse and generate JSON without any intermediate step

    See documentation and examples at https://docs.cesanta.com/frozen

    Source code(tar.gz)
    Source code(zip)
Owner
Cesanta Software
Embedded Communication
Cesanta Software
https://github.com/json-c/json-c is the official code repository for json-c. See the wiki for release tarballs for download. API docs at http://json-c.github.io/json-c/

\mainpage json-c Overview and Build Status Building on Unix Prerequisites Build commands CMake options Testing Building with vcpkg Linking to libjson-

json-c 2.5k Sep 26, 2022
RapidJSON is a JSON parser and generator for C++.

A fast JSON parser/generator for C++ with both SAX/DOM style API

Tencent 12.4k Oct 2, 2022
A fast JSON parser/generator for C++ with both SAX/DOM style API

A fast JSON parser/generator for C++ with both SAX/DOM style API Tencent is pleased to support the open source community by making RapidJSON available

Tencent 12.4k Sep 28, 2022
A generator of JSON parser & serializer C++ code from structure header files

JSON-CPP-gen This is a program that parses C++ structures from a header file and automatically generates C++ code capable of serializing said structur

Viktor Chlumský 10 Aug 20, 2022
Json For Embedded Systems (JFES)

JFES Based on the jsmn project. Json For Embedded Systems (JFES) is a minimalistic json engine written in plain C. It can be easily integrated into th

Eremin Dmitrii 65 Jul 4, 2022
📟 JSON library for Arduino and embedded C++. Simple and efficient.

ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things). Features JSON deserialization Optionally decodes UTF-16 escape sequences t

Benoît Blanchon 5.8k Sep 27, 2022
This is a JSON C++ library. It can write and read JSON files with ease and speed.

Json Box JSON (JavaScript Object Notation) is a lightweight data-interchange format. Json Box is a C++ library used to read and write JSON with ease a

Anhero inc. 108 Aug 26, 2022
🗄️ single header json parser for C and C++

??️ json.h A simple single header solution to parsing JSON in C and C++. JSON is parsed into a read-only, single allocation buffer. The current suppor

Neil Henning 513 Sep 24, 2022
a JSON parser and printer library in C. easy to integrate with any model.

libjson - simple and efficient json parser and printer in C Introduction libjson is a simple library without any dependancies to parse and pretty prin

Vincent Hanquez 262 Sep 29, 2022
single-header json parser for c99 and c++

ghh_json.h a single-header ISO-C99 (and C++ compatible) json loader. why? obviously this isn't the first json library written for C, so why would I wr

garrison hinson-hasty 15 May 26, 2022
Ultralightweight JSON parser in ANSI C

cJSON Ultralightweight JSON parser in ANSI C. Table of contents License Usage Welcome to cJSON Building Copying the source CMake Makefile Vcpkg Includ

Dave Gamble 8k Sep 29, 2022
JSON & BSON parser/writer

jbson is a library for building & iterating BSON data, and JSON documents in C++14. \tableofcontents Features # {#features} Header only. Boost license

Chris Manning 40 Sep 14, 2022
Jsmn is a world fastest JSON parser/tokenizer. This is the official repo replacing the old one at Bitbucket

JSMN jsmn (pronounced like 'jasmine') is a minimalistic JSON parser in C. It can be easily integrated into resource-limited or embedded projects. You

Serge Zaitsev 3.1k Oct 3, 2022
A JSON parser in C++

JSON++ Introduction JSON++ is a light-weight JSON parser, writer and reader written in C++. JSON++ can also convert JSON documents into lossless XML d

Hong Jiang 488 Sep 13, 2022
Very low footprint JSON parser written in portable ANSI C

Very low footprint JSON parser written in portable ANSI C. BSD licensed with no dependencies (i.e. just drop the C file into your project) Never recur

James McLaughlin 1.2k Sep 30, 2022
Very simple C++ JSON Parser

Very simple JSON parser for c++ data.json: { "examples": [ { "tag_name": "a", "attr": [ { "key":

Amir Saboury 65 Sep 28, 2022
a header-file-only, JSON parser serializer in C++

PicoJSON - a C++ JSON parser / serializer Copyright © 2009-2010 Cybozu Labs, Inc. Copyright © 2011-2015 Kazuho Oku Licensed under 2-clause BSD license

Kazuho Oku 1k Sep 27, 2022
Lightweight, extremely high-performance JSON parser for C++11

sajson sajson is an extremely high-performance, in-place, DOM-style JSON parser written in C++. Originally, sajson meant Single Allocation JSON, but i

Chad Austin 541 Sep 16, 2022
🔋 In-place lightweight JSON parser

?? JSON parser for C This is very simple and very powerful JSON parser. It creates DOM-like data structure and allows to iterate and process JSON obje

Recep Aslantas 22 Sep 14, 2022