jsoncc is a tool to generate C99 compliant source code for decoding and encoding C structs to JSON.
It is heavy work in progress ... so in the futre the generated code might change a lot
Just clone it and you are ready to go. It works on *nix based systems on Windows it was never been tested
Python 2.7
jsoncc expects as a input one .h
file where the structs are declared
using a typedef with no typedef struct are ignored ATM. As an output
it creates a .c
and .h
files where all the necessary code is
generated, all you need to do is to include the .h
in your source
where appropriate and add the .c
, frozen.c
and frozen.h
files (find them in the test directory) to your build.
jsoncc/jsoncc.py -i source.h -o output
Creates output.h
and output.c
files from source.h
For help see jsoncc/jsoncc.py -h
Or you can import the JsonCC class from the jsoncc package.
from jsoncc.jsoncc import JsonCC
jsoncc = JsonCC(src=code, filename=args.input[0], output=args.output[0], debug=True/False, parse_debug=True/false)
jsoncc.gen()
Anything related to jsoncc is introduced by //+json:
comment.
If you want the struct to be encoded use //+json:encode
and
//+json:decode
for decoding.
Encoding takes the struct and creates a JSON object {...}
from it by
using the names of the struct members as keys and their values as
values.
To encode JSON boolean use an int type and indicate that is should be
a bool on the same line comment //+json:boolean
To encode char *
as a already encoded JSON data use //+json:json
otherwise this type is treated as a string and is in the quotes " ... "
. This is the only optional value in the struct, that mean it
can be NULL
and then JSON null
is used.
There is no way how to encode structs in struct or even arrays, this
is a feature which is underway. At the moment you can included in the
struct as a JSON string. To encode a struct to JSON array add an array
flag to encoding line //+json:encode:array
which creates an array
from the struct instead of a JSON object.
Generated function to encode a struct is in following format
jsn_error_t jsn_encode_(typedef name - _t or _s)(typedef name *s, char **buf, size_t *len)
.
//+json:encode
typedef struct trace_get_desc_rq_s
{
char *actID; //+json:optional
int valid; //+json:boolean
int userID ;
char *inner; //+json:json
} trace_get_desc_rq_t ;
generates function
jsn_error_t jsn_encode_trace_get_desc_rq(trace_get_desc_rq_t *s, char **buf, size_t *len);
Decoding works quite differently than encoding as it assumes that you don't really need all the stuff in th JSON data or that you want a different mapping and therefore you have to annotate each of the items in the struct.
Each member which should be decoded needs a comment in form
//+json:<path to the item in the json>
if it is omitted than the
decoding function will ignore such member. A path
is a string, an
accessor to the desired element of the JSON object, as if it was
written in Javascript. For example, if parsed JSON string is { foo : { bar: [1, 2, 3] } }
, then path is foo.bar[0]
Arrays are decoded if the item in the struct is declared as a pointer,
except for char *
where char **
is interpreted as a string
array. It also expect that in the struct is a int <varname>_count_
member where it stores number of items. String arrays are different
there the last item in the array is NULL
and therefore there is no
need to store the count.
Generated function to decode into the struct is in following format
jsn_error_t jsn_decode_(typedef name - _t or _s)(typedef name *s, char * json_data, size_t json_len)
.
To make it easier to use, there is a option free
to generate clenup
functions for decoded structs so there is no need to track what is
malloc'ed and what not, just call the corresponding cleanup function
named void jsn_free_(typedef name - _t or _s)(typedef name *s)
.
It frees any memory allocated in the decode function not the struct
itself. If you don't want any of it just omit the the option.
//+json:decode:free
typedef struct trace_desc_s
{
int activedays; //+json:user.activeDays
char *domain; //+json:user.domain:optional
char **states; //+json:user.state:optional
int *statenos; //+json:user.stateno
int statenos_count_;
char *gatewayurl; //+json:userServer[0].url
char *eventurl; //+json:userServer[0].events.url
float lat; //+json:user.location.latitude
double lon; //+json:user.location.longitude
} trace_desc_t ;
generates functions
jsn_error_t jsn_decode_trace_desc(trace_desc_t *s, char *json_data, size_t json_len);
void jsn_free_trace_desc(trace_desc_t *s);
See test directory for working example.
This tool is based on modified Eli Bendersky's pycparser and json parsing on frozen parser.