How to parse a small JSON file with jsmn on an embedded system? How to parse a small JSON file with jsmn on an embedded system? json json

How to parse a small JSON file with jsmn on an embedded system?


jsmn will give you a set of tokens referring to the tokens in your JSON reading left to right.

In your case:

token[0]: (outer) object, 2 childrentoken[1]: string token ("data1")token[2]: array, 9 childrentoken[3]: primitive token (1)etc...

The basic code to do the parsing is:

int resultCode;jsmn_parser p;jsmntok_t tokens[128]; // a number >= total number of tokensjsmn_init(&p);resultCode = jsmn_parse(&p, yourJson, tokens, 256);

The other trick is getting the value of a token. The token contains the start and end points of the data on your original string.

jsmntok_t key = tokens[1];unsigned int length = key.end - key.start;char keyString[length + 1];    memcpy(keyString, &yourJson[key.start], length);keyString[length] = '\0';printf("Key: %s\n", keyString);

With that you should be able to figure you how to iterate through your data.


I was curious as about this as well, so I made a small program to show the structure of the tokens array:

This program:

#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include "jsmn.h"jsmntok_t t[512];char jsonStr[512*1024];int main(){  size_t pos = 0;  int    c;  while ((c = getchar()) != EOF)  {    jsonStr[pos] = c;    ++pos;    if (pos == sizeof(jsonStr)) break;  }  jsonStr[pos] = 0;  jsmn_parser p;  jsmn_init(&p);  int tCount = jsmn_parse(&p, jsonStr, strlen(jsonStr), t, sizeof(t)/sizeof(*t));  for (int i = 0; i != tCount; ++i)  {    jsmntok_t *token = t + i;    char * type = 0;    switch (token->type)    {      case JSMN_PRIMITIVE:        type = "PRIMITIVE";        break;      case JSMN_OBJECT:        type = "OBJECT";        break;      case JSMN_ARRAY:        type = "ARRAY";        break;      case JSMN_STRING:        type = "STRING";        break;      default:        type = "UNDEF";    }#ifdef JSMN_PARENT_LINKS    printf("node: %4d, %9s, parent: %4d, children: %5d, data:\n%.*s, \n", i, type, token->parent, token->size, token->end-token->start, jsonStr+token->start);#else    printf("node: %4d, %9s, children: %5d, data:\n%.*s, \n", i, type, token->size, token->end-token->start, jsonStr+token->start);#endif  }}

prints this json (taken from: https://en.wikipedia.org/wiki/JSON):

{  "firstName": "John",  "lastName": "Smith",  "isAlive": true,  "age": 25,  "address": {    "streetAddress": "21 2nd Street",    "city": "New York",    "state": "NY",    "postalCode": "10021-3100"  },  "phoneNumbers": [    {      "type": "home",      "number": "212 555-1234"    },    {      "type": "office",      "number": "646 555-4567"    },    {      "type": "mobile",      "number": "123 456-7890"    }  ],  "children": [],  "spouse": null}

as:

node:    0,    OBJECT, parent:   -1, children:     8, data:{  "firstName": "John",  "lastName": "Smith",  "isAlive": true,  "age": 25,  "address": {    "streetAddress": "21 2nd Street",    "city": "New York",    "state": "NY",    "postalCode": "10021-3100"  },  "phoneNumbers": [    {      "type": "home",      "number": "212 555-1234"    },    {      "type": "office",      "number": "646 555-4567"    },    {      "type": "mobile",      "number": "123 456-7890"    }  ],  "children": [],  "spouse": null},node:    1,    STRING, parent:    0, children:     1, data:firstName,node:    2,    STRING, parent:    1, children:     0, data:John,node:    3,    STRING, parent:    0, children:     1, data:lastName,node:    4,    STRING, parent:    3, children:     0, data:Smith,node:    5,    STRING, parent:    0, children:     1, data:isAlive,node:    6, PRIMITIVE, parent:    5, children:     0, data:true,node:    7,    STRING, parent:    0, children:     1, data:age,node:    8, PRIMITIVE, parent:    7, children:     0, data:25,node:    9,    STRING, parent:    0, children:     1, data:address,node:   10,    OBJECT, parent:    9, children:     4, data:{    "streetAddress": "21 2nd Street",    "city": "New York",    "state": "NY",    "postalCode": "10021-3100"  },node:   11,    STRING, parent:   10, children:     1, data:streetAddress,node:   12,    STRING, parent:   11, children:     0, data:21 2nd Street,node:   13,    STRING, parent:   10, children:     1, data:city,node:   14,    STRING, parent:   13, children:     0, data:New York,node:   15,    STRING, parent:   10, children:     1, data:state,node:   16,    STRING, parent:   15, children:     0, data:NY,node:   17,    STRING, parent:   10, children:     1, data:postalCode,node:   18,    STRING, parent:   17, children:     0, data:10021-3100,node:   19,    STRING, parent:    0, children:     1, data:phoneNumbers,node:   20,     ARRAY, parent:   19, children:     3, data:[    {      "type": "home",      "number": "212 555-1234"    },    {      "type": "office",      "number": "646 555-4567"    },    {      "type": "mobile",      "number": "123 456-7890"    }  ],node:   21,    OBJECT, parent:   20, children:     2, data:{      "type": "home",      "number": "212 555-1234"    },node:   22,    STRING, parent:   21, children:     1, data:type,node:   23,    STRING, parent:   22, children:     0, data:home,node:   24,    STRING, parent:   21, children:     1, data:number,node:   25,    STRING, parent:   24, children:     0, data:212 555-1234,node:   26,    OBJECT, parent:   20, children:     2, data:{      "type": "office",      "number": "646 555-4567"    },node:   27,    STRING, parent:   26, children:     1, data:type,node:   28,    STRING, parent:   27, children:     0, data:office,node:   29,    STRING, parent:   26, children:     1, data:number,node:   30,    STRING, parent:   29, children:     0, data:646 555-4567,node:   31,    OBJECT, parent:   20, children:     2, data:{      "type": "mobile",      "number": "123 456-7890"    },node:   32,    STRING, parent:   31, children:     1, data:type,node:   33,    STRING, parent:   32, children:     0, data:mobile,node:   34,    STRING, parent:   31, children:     1, data:number,node:   35,    STRING, parent:   34, children:     0, data:123 456-7890,node:   36,    STRING, parent:    0, children:     1, data:children,node:   37,     ARRAY, parent:   36, children:     0, data:[],node:   38,    STRING, parent:    0, children:     1, data:spouse,node:   39, PRIMITIVE, parent:   38, children:     0, data:null,


You can use tiny-json. It gives you more than tokens. I have used with microcontrollers of 16-bits and 32-bits and it works fine.

char str[] = "{"                 "\"data1\":[1,2,3,4,5,6,7,8,9],"                 "\"data2\":["                     "[3,4,5,6,1],"                     "[8,4,5,6,1],"                     "[10,4,5,3,61],"                     "[3,4,5,6,1],"                     "[3,4,5,6,1],"                     "[3,4,5,6,1]"                 "]"             "}";puts( str );json_t pool[64];json_t const* root = json_create( str, pool, 64 );json_t const* data1 = json_getProperty( root, "data1" );if ( data1 && JSON_ARRAY == json_getType( data1 ) ) {    json_t const* field = json_getChild( data1 );    while( field ) {        if ( JSON_INTEGER == json_getType( field ) ) {            long long int data = json_getInteger( field );            printf("Integer from data1: %lld\n", data );        }        field = json_getSibling( field );    }}json_t const* data2 = json_getProperty( root, "data2" );if ( data2 && JSON_ARRAY == json_getType( data2 ) ) {    json_t const* array = json_getChild( data2 );    while( array ) {        if ( JSON_ARRAY == json_getType( array ) ) {            puts("Array in data2");            json_t const* field = json_getChild( array );            while( field ) {                if ( JSON_INTEGER == json_getType( field ) ) {                    long long int data = json_getInteger( field );                    printf("Integer from array of data2: %lld\n", data );                }                field = json_getSibling( field );             }        }        array = json_getSibling( array );    }}