Skip to content

w-vi/jsoncc

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

JSONCC

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

Install

Just clone it and you are ready to go. It works on *nix based systems on Windows it was never been tested

Requirements

Python 2.7

Usage

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()

How to annotate the source code

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

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).

Example:

//+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

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.

Example

//+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);

Example

See test directory for working example.

Acknowledgment

This tool is based on modified Eli Bendersky's pycparser and json parsing on frozen parser.

About

Json encoding decoding C99 generator

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages