Giter Site home page Giter Site logo

json-maker's Introduction

JSON Maker

Build Status

JSON Maker is a C library used to code JSON objects in null-terminated strings.

Surely the most effective method to create simple JSON objects is to use sprintf. But when you need to reuse code, nest objects or include arrays you can fall into the formatted-strings hell.

  • Backslash escapes are automatically added. Only in the fields of type string.
  • By means of compilation options, the use of print can be avoided. This is very useful in embedded systems with memory constraint.

If you need a JSON parser please visit: https://github.com/rafagafe/tiny-json

Philosophy

To form JSON objects in strings of characters are invoked sequences of functions that concatenate sub-strings. Each substring includes a field of the JSON object, key-value. To add fields of the type object or array you need to invoke two functions, one to open and another to close.

struct weather {
    int temp;
    int hum;
};

/** Convert a weather structure in a JSON string.
  * @param dest Destination memory block.
  * @param src Source structure.
  * @return The length of the null-terminated string in dest. */
int weather_to_json( char* dest, struct weather const* src ) {
    char* p = dest;                       // p always points to the null character
    p = json_objOpen( p, NULL );          // --> {\0
    p = json_int( p, "temp", src->temp ); // --> {"temp":22,\0
    p = json_int( p, "hum", src->hum );   // --> {"temp":22,"hum":45,\0
    p = json_objClose( p );               // --> {"temp":22,"hum":45},\0
    p = json_end( p );                    // --> {"temp":22,"hum":45}\0
    return p - dest;       
}
    

The complexity of these sequences of concatenations is kept in O(n) thanks to the fluent interface of JSON Maker.

It is very easy to extend the library by creating methods to convert C structures into JSON fields of object type. As with the arrays.

struct weather {
    int temp;
    int hum;
};

/* Add a time object property in a JSON string.
  "name":{"temp":-5,"hum":48}, */
char* json_weather( char* dest, char const* name, struct weather const* weather ) {
    // dest always points to the null character
    dest = json_objOpen( dest, name );              // --> "name":{\0
    dest = json_int( dest, "temp", weather->temp ); // --> "name":{"temp":22,\0
    dest = json_int( dest, "hum", weather->hum );   // --> "name":{"temp":22,"hum":45,\0
    dest = json_objClose( dest );                   // --> "name":{"temp":22,"hum":45},\0
    return dest;
}

struct time {
    int hour;
    int minute;
};

/* Add a time object property in a JSON string.
  "name":{"hour":18,"minute":32}, */
char* json_time( char* dest, char const* name, struct time const* time ) {
    dest = json_objOpen( dest, name );
    dest = json_int( dest, "hour",   time->hour   );
    dest = json_int( dest, "minute", time->minute );
    dest = json_objClose( dest );
    return dest;
}

struct measure {
    struct weather weather;
    struct time time;
};

/** Convert a weather structure in a JSON string.
  * {"weather":{"temp":-5,"hum":48},"time":{"hour":18,"minute":32}}
  * @param dest Destination memory block.
  * @param src Source structure.
  * @return The length of the null-terminated string in dest. */
int measure_to_json( char* dest, struct measure const* measure ) {
    char* p = json_objOpen( dest, NULL );
    p = json_weather( p, "weather", &measure->weather );
    p = json_time( p, "time", &measure->time );
    p = json_objClose( p );
    p = json_end( p );
    return p - dest;
}

To see more nested JSON objects and arrays please read example.c.

#Building and Testing

JSON Maker is built as a static library. JSON Maker relies on CMake and CTest for building and testing (see https://cmake.org/ for more information).

The library is found under {project_root}/build/lib/static, the executables under {project_root}/build/bin.

Two configurations are supported, Debug and Release. You can use option CMAKE_BUILD_TYPE to change from the default (Debug). The following examples assume Debug builds, except for install which uses Release.

Create the build folder

mkdir build
cd build

##Building the static library

cmake --configure ..
cmake --build .

##Installing the static library if you are not super-user or don't want to use sudo you can install the library in your home's opt folder.

cmake --configure -DCMAKE_BUILD_TYPE=Release..
cmake --build .

As sudo/root (will use default /usr/local/ on Unix)

cmake --install .

As a regular user

cmake --install . --prefix $HOME/opt

##Building the sample application

cmake --configure -DBUILD_SAMPLES=ON ..
cmake --build .

##Runing the tests

cmake --configure ..
cmake --build .
cd tests
ctest .

json-maker's People

Contributors

alcantor avatar antgeorge avatar caleb-daniels-sfc avatar hpfaz avatar jaymin1328 avatar rafagafe avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

json-maker's Issues

remLen is not correctly updated in the jfson_num function

Thanks for the great software!
During integration I found some inconsistencies when adding numbers to the json string.
The remLen variable did not update on the length of the number.

Changing json_num in the following manner seems to fix this:

#define json_num( funcname, type, fmt )
char* funcname( char* dest, char const* name, type value, size_t* remLen ) {
dest = primitivename( dest, name, remLen );
int len = snprintf( dest, *remLen, fmt, value );
dest += len;
*remLen -= len;
dest = chtoa( dest, ',', remLen );
return dest;
}

all the best,
Mike

Double len

Hi! How do I set the output format for double? Example of how this is set for sprintf "%3.6f"

Protection against buffer overrun

Hi,

Thanks for publishing this library! I have just been looking at using it in an embedded project, but it seems that when constructing json objects, it is possible to overrun the string buffer without knowing. Perhaps it is worth adding an argument (or a series of โ€œ_sโ€ suffixed methods) which take an additional length parameter and checks that the length of the string does not increase beyond the allocated buffer length ?

Solidus character is escaped

Does the solidus character needs to be escaped?
Per the rfc https://www.ietf.org/rfc/rfc4627.txt

All Unicode characters may be placed within the
quotation marks except for the characters that must be escaped:
quotation mark, reverse solidus, and the control characters (U+0000
through U+001F).

the solidus doesn't require mandatorily to be escaped. So is it really required ?

error: too few arguments to function 'json_objOpen'

prototype in json-maker.h is
char* json_objOpen( char* dest, char const* name, size_t* remLen );

but the sample code is...
dest = json_objOpen( dest, name );

also noticed the code looked suspiciously reactionary to buffer overflow at...

   char buff[512];
    int len = data_to_json( buff, &data );
    if( len >= sizeof buff ) {
        fprintf( stderr, "%s%d%s%d\n", "Error. Len: ", len, " Max: ", (int)sizeof buff - 1 );
        return EXIT_FAILURE;
    }

betting that issue was fixed, but the sample code wasn't updated.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.