GitHub hosted
Public

Mbed library for json, using jRead and jWrite



Download repository: zip

jReadWrite

JSON Library for use with Mbed-OS

Credit to Tony Wilk

Introduction

jReadWrite is an Mbed library composed of jWrite and jRead.

jWrite is a simple way of writing JSON to a char buffer in C, directly from native variables. It manages the output buffer so you don’t overrun, it handles all the fiddly quotes, brackets and commas and reports where you have tried to create invalid JSON.

jRead is a simple in-place JSON element reader, it maintains the input JSON as unaltered text and allows queries to be made on it directly. Written in C, jRead is small, fast and does not allocate any memory - making it an ideal choice for embedded applications or those cases where all you want is to read a few values from a chunk of JSON without having to learn a large API and have your program generate lots of interlinked structures to represent the JSON.

Getting Started

Here is an Mbed example project mbed-json-example

Adding a library to your project

Use mbed add to add the latest revision of a library:

$ mbed add https://github.com/jonaskgandersson/jReadWrite

Use the URL#hash format to add a library from a URL at a specific revision hash:

$ mbed add https://github.com/jonaskgandersson/jReadWrite/#6dd542b2814768fdc6ca0aaea7529dfcb9bee37f

jWrite

Jumping straight in:

struct jWriteControl jwc;
jwOpen( &jwc, buffer, buflen, JW_OBJECT, JW_PRETTY );  // open root node as object
jwObj_string( &jwc, "key", "value" );                  // writes "key":"value"
jwObj_int( &jwc, "int", 1 );                           // writes "int":1
jwObj_array( &jwc, "anArray");                         // start "anArray": [...] 
    jwArr_int( &jwc, 0 );                              // add a few integers to the array
    jwArr_int( &jwc, 1 );
    jwArr_int( &jwc, 2 );
jwEnd( &jwc );                                         // end the array
err= jwClose( &jwc );                                  // close root object - done

which results in:

{
    "key": "value",
    "int": 1,
    "anArray": [
        0,
        1,
        2
    ]
}

The output is prettyfied (it’s an option) and has all the { } [ ] , : ” characters in the right place.

To Be, or Not To Be, GLOBAL

For many applications it is a lot simpler to have one global (static) instance of a structure which can be used for jWrite, it makes the API calls easy to type in - you don’t have to supply a reference every time.

The above example with JW_GLOBAL_CONTROL_STRUCT set to true in mbed_lib.json:

jwOpen( buffer, buflen, JW_OBJECT, JW_PRETTY );  // open root node as object
jwObj_string( "key", "value" );                  // writes "key":"value"
jwObj_int( "int", 1 );                           // writes "int":1
jwObj_array( "anArray");                         // start "anArray": [...] 
    jwArr_int( 0 );                              // add a few integers to the array
    jwArr_int( 1 );
    jwArr_int( 2 );
jwEnd();                                         // end the array
err= jwClose();                                  // close root object - done

However, that is not very flexible and does not allow for multiple uses of jWrite functions at the same time.

jRead

Basically, the API is a single function call:

jRead( pJsonText, pQueryString, pOutputStruct );

The Query String defines how to traverse the JSON to end up with a value which is returned to pOutputStruct . Elements of a query can be as follows:

"{'keyname'"           Object element "keyname", returns value of that key
"{NUMBER"              Object element[NUMBER], returns keyname of that element
"[NUMBER"              Array element[NUMBER], returns value from array

Examples of What jRead Does
Assume we have a simple JSON string we have read into some buffer pJson like:

{
    "astring":"This is a string",
    "anumber":42,
    "myarray":[ "zero", 1, {"description":"element 2"}, null ],
    "yesno":true,
    "PI":"3.1415926",
    "foo":null
}

we can get the value of any element using jRead, e.g.,

struct jReadElement result;
jRead( pJson, "{'astring'", &result );

In this case, the result would be:

result.dataType= JREAD_STRING
result.elements= 1
result.byteLen=  16
result.pValue -> "This is a string"

Note that nothing is copied, the result structure simply gives you a pointer to the start of the element and its length.

The helper functions make it easy to extract single values into C variables like:

jRead_string( pJson, "{'astring'", destString, MAXLEN, NULL );  // This is a string
my_int = jRead_int( pJson, "{'myarray'[1", NULL );      // 1
my_long = jRead_long( pJson, "{'anumber'", NULL );      // 42
my_double = jRead_double( pJson, "{'PI'", NULL );       // 3.1415926

Note that the ‘int’ helper does some ‘type coersion’ - since everything is a string anyway, calling jReadInt() will always return a value: it will return 42 for the JSON 42 or “42” and returns zero for “foo”. It also returns 1 for true and 0 for false or null.

Compiled with

Contributing

When contributing to this repository, please first discuss the change you wish to make via issue, email, or any other method with the owners of this repository before making a change.

Versioning

We use SemVer for versioning. For the versions available, see the tags on this repository.

Authors

License

This project is licensed under the Apache License - see the LICENSE file for details

Acknowledgments

  • Hat tip to Tony Wilk for sharing his great code.