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 the code for embedded systems.
- compatible with C99
- no dependencies (I'm serious!)
- highly portable
- you can use it as a json parser only
- incremental single-pass parsing
Before use you need to initialize the jfes_config_t
object.
/** JFES config structure. */
typedef struct jfes_config {
jfes_malloc_t jfes_malloc; /**< Memory allocation function. */
jfes_free_t jfes_free; /**< Memory deallocation function. */
} jfes_config_t;
Below you can see the prototypes of the memory management functions:
/** Memory allocator function type. */
typedef void *(__cdecl *jfes_malloc_t)(jfes_size_t);
/** Memory deallocator function type. */
typedef void (__cdecl *jfes_free_t)(void*);
As you can see, these functions have the same prototype as the C standard library functions.
So, you can initialize JFES configuration with the following code:
#include <stdlib.h>
/* ...some useful stuff... */
jfes_config_t config;
config.jfes_malloc = malloc;
config.jfes_free = free;
But, if you need to use your own memory management functions, you can use them.
If you just need to parse a *.json file without allocating any values (like jsmn), you can parse a json string and separate it into tokens. In this case, you only need to use two functions below:
/**
JFES parser initialization.
\param[out] parser Pointer to the jfes_parser_t object.
\param[in] config JFES configuration.
\return jfes_success if everything is OK.
*/
jfes_status_t jfes_init_parser(jfes_parser_t *parser, jfes_config_t *config);
/******************************************************************/
/**
Run JSON parser. It parses a JSON data string into and
array of tokens, each describing a single JSON object.
\param[in] parser Pointer to the jfes_parser_t object.
\param[in] json JSON data string.
\param[in] length JSON data length.
\param[out] tokens Tokens array to fill.
\param[in, out] max_tokens_count Maximal count of tokens in tokens array.
Will contain tokens count.
\return jfes_success if everything is OK.
*/
jfes_status_t jfes_parse_tokens(jfes_parser_t *parser, const char *json,
jfes_size_t length, jfes_token_t *tokens, jfes_size_t *max_tokens_count);
You can see a parsing example below.
You can load any json data into jfes_value_t
.
/** JSON value structure. */
struct jfes_value {
jfes_value_type_t type; /**< JSON value type. */
jfes_value_data_t data; /**< Value data. */
};
Value type (jfes_value_type_t
) can be one of the following:
jfes_type_boolean
jfes_type_integer
jfes_type_double
jfes_type_string
jfes_type_array
jfes_type_object
And jfes_value_data_t
is:
/** JFES value data union. */
typedef union jfes_value_data {
int bool_val; /**< Boolean JSON value. */
int int_val; /**< Integer JSON value. */
double double_val; /**< Double JSON value. */
jfes_string_t string_val; /**< String JSON value. */
jfes_array_t *array_val; /**< Array JSON value. */
jfes_object_t *object_val; /**< Object JSON value. */
} jfes_value_data_t;
You can easily load a json string into the value by using the following code:
jfes_config_t config;
config.jfes_malloc = malloc;
config.jfes_free = free;
jfes_value_t value;
jfes_parse_to_value(&config, json_data, json_size, &value);
/* Do something with value */
jfes_free_value(&config, &value);
That's all!
You can modify or create jfes_value_t
with any of these functions:
jfes_value_t *jfes_create_boolean_value(jfes_config_t *config, int value);
jfes_value_t *jfes_create_integer_value(jfes_config_t *config, int value);
jfes_value_t *jfes_create_double_value(jfes_config_t *config, double value);
jfes_value_t *jfes_create_string_value(jfes_config_t *config, const char *value, jfes_size_t length);
jfes_value_t *jfes_create_array_value(jfes_config_t *config);
jfes_value_t *jfes_create_object_value(jfes_config_t *config);
jfes_value_t *jfes_get_child(jfes_value_t *value, const char *key, jfes_size_t key_length);
jfes_object_map_t *jfes_get_mapped_child(jfes_value_t *value, const char *key, jfes_size_t key_length);
jfes_status_t jfes_place_to_array(jfes_config_t *config, jfes_value_t *value, jfes_value_t *item);
jfes_status_t jfes_place_to_array_at(jfes_config_t *config, jfes_value_t *value, jfes_value_t *item, jfes_size_t place_at);
jfes_status_t jfes_remove_from_array(jfes_config_t *config, jfes_value_t *value, jfes_size_t index);
jfes_status_t jfes_set_object_property(jfes_config_t *config, jfes_value_t *value, jfes_value_t *item, const char *key, jfes_size_t key_length);
jfes_status_t jfes_remove_object_property(jfes_config_t *config, jfes_value_t *value, const char *key, jfes_size_t key_length);
You can serialize any jfes_value_t
to string with one line (actually, three lines, but two of them are for help):
char dump[1024];
jfes_size_t dump_size = 1024;
jfes_value_to_string(&value, beauty_dump, &dump_size, 1);
beauty_dump[dump_size] = '\0'; /* If you need null-terminated string. */
dump_size
will store the dump size.
If you pass the fourth argument as 1, the dump will be beautified. And if 0, the dump will be ugly.
You can find examples here.
The MIT License (MIT)
See full text.