JSON library based on JSMN lib

Dependents:   ATT_WNCInterface_Info WNCInterface_HTTP_example NerfUS-Coord Mbed_Prototype_copy_4_INNO_day_15_6_2017 ... more

C++ JSON wrapper over JSMN lib (https://github.com/zserge/jsmn).

This C++ Class is a set of common tools/procedures as a C++ wrapper over JSMN JSON parser library. It is intended to provide the boiler-plate code, with intentions to reduce code clutter, in more of C++ fashion.

In contrast to original library, Json is intended to work strictly with valid JSON structures. Non-standard JSON structures should result in an error.

This class works explicitly on the indices returned by underlying JSMN library. In the scope of this class, its function parameters, return types, and documentation, the term 'index' will always mean the index of JSMN tokens, parsed by the Json constructor, unless and until explicitly mentioned otherwise.

Committer:
faheem_chaudhary
Date:
Tue Aug 02 20:21:04 2016 +0000
Revision:
4:ae34010d87e5
Parent:
3:fab591fca1e7
Child:
5:dd98cf00ed9b
Added Key search in flat format

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mercurywaters 0:7f4a18b3fd82 1 #include "Json.h"
mercurywaters 0:7f4a18b3fd82 2
mercurywaters 0:7f4a18b3fd82 3 Json::Json ( const char * jsonString, size_t length )
mercurywaters 3:fab591fca1e7 4 : source ( jsonString ), sourceLength ( length )
mercurywaters 0:7f4a18b3fd82 5 {
mercurywaters 0:7f4a18b3fd82 6 jsmn_parser parser;
mercurywaters 3:fab591fca1e7 7 int count = 100; //jsmn_parse ( &parser, jsonString, length, NULL, 16384 );
mercurywaters 0:7f4a18b3fd82 8 tokens = new jsmntok_t [ count ];
mercurywaters 3:fab591fca1e7 9
mercurywaters 0:7f4a18b3fd82 10 jsmn_init ( &parser );
mercurywaters 0:7f4a18b3fd82 11 tokenCount = jsmn_parse ( &parser, jsonString, length, tokens, count );
mercurywaters 0:7f4a18b3fd82 12 }
mercurywaters 0:7f4a18b3fd82 13
mercurywaters 3:fab591fca1e7 14 Json::Json ( const Json & other )
mercurywaters 3:fab591fca1e7 15 : source ( NULL ), sourceLength ( 0 )
mercurywaters 3:fab591fca1e7 16 {
mercurywaters 3:fab591fca1e7 17 tokenCount = 0;
mercurywaters 3:fab591fca1e7 18 tokens = NULL;
mercurywaters 3:fab591fca1e7 19 }
mercurywaters 3:fab591fca1e7 20
mercurywaters 3:fab591fca1e7 21 Json::~Json ()
mercurywaters 0:7f4a18b3fd82 22 {
mercurywaters 0:7f4a18b3fd82 23 delete [] tokens;
mercurywaters 0:7f4a18b3fd82 24 }
mercurywaters 0:7f4a18b3fd82 25
faheem_chaudhary 4:ae34010d87e5 26 int Json::findKeyIndex ( const char * key, const int &startingAt ) const
faheem_chaudhary 4:ae34010d87e5 27 {
faheem_chaudhary 4:ae34010d87e5 28 int retVal = -1;
faheem_chaudhary 4:ae34010d87e5 29
faheem_chaudhary 4:ae34010d87e5 30 int i = startingAt + 1;
faheem_chaudhary 4:ae34010d87e5 31 if ( i < 0 ) {
faheem_chaudhary 4:ae34010d87e5 32 i = 0;
faheem_chaudhary 4:ae34010d87e5 33 }
faheem_chaudhary 4:ae34010d87e5 34
faheem_chaudhary 4:ae34010d87e5 35 for ( ; i < tokenCount; i++ )
faheem_chaudhary 4:ae34010d87e5 36 {
faheem_chaudhary 4:ae34010d87e5 37 jsmntok_t t = tokens [ i ];
faheem_chaudhary 4:ae34010d87e5 38
faheem_chaudhary 4:ae34010d87e5 39 if ( t.type == JSMN_KEY )
faheem_chaudhary 4:ae34010d87e5 40 {
faheem_chaudhary 4:ae34010d87e5 41 size_t keyLength = (size_t) ( t.end - t.start );
faheem_chaudhary 4:ae34010d87e5 42 if ( ( strlen ( key ) == keyLength ) && ( strncmp ( source + t.start, key, keyLength ) == 0 ) )
faheem_chaudhary 4:ae34010d87e5 43 {
faheem_chaudhary 4:ae34010d87e5 44 retVal = i;
faheem_chaudhary 4:ae34010d87e5 45 break;
faheem_chaudhary 4:ae34010d87e5 46 }
faheem_chaudhary 4:ae34010d87e5 47 }
faheem_chaudhary 4:ae34010d87e5 48 }
faheem_chaudhary 4:ae34010d87e5 49
faheem_chaudhary 4:ae34010d87e5 50 return retVal;
faheem_chaudhary 4:ae34010d87e5 51 }
faheem_chaudhary 4:ae34010d87e5 52
mercurywaters 0:7f4a18b3fd82 53 int Json::findKeyIndexIn ( const char * key, const int &parentIndex ) const
mercurywaters 0:7f4a18b3fd82 54 {
mercurywaters 0:7f4a18b3fd82 55 int retVal = -1;
mercurywaters 3:fab591fca1e7 56
mercurywaters 3:fab591fca1e7 57 if ( parentIndex != -1 && parentIndex < tokenCount )
mercurywaters 3:fab591fca1e7 58 {
mercurywaters 3:fab591fca1e7 59
mercurywaters 3:fab591fca1e7 60 for ( int i = parentIndex + 1; i < tokenCount; i++ )
mercurywaters 3:fab591fca1e7 61 {
mercurywaters 3:fab591fca1e7 62
mercurywaters 0:7f4a18b3fd82 63 jsmntok_t t = tokens [ i ];
mercurywaters 3:fab591fca1e7 64
mercurywaters 3:fab591fca1e7 65 if ( t.end >= tokens [ parentIndex ].end )
mercurywaters 3:fab591fca1e7 66 {
mercurywaters 0:7f4a18b3fd82 67 break;
mercurywaters 0:7f4a18b3fd82 68 }
mercurywaters 3:fab591fca1e7 69
mercurywaters 3:fab591fca1e7 70 if ( ( t.type == JSMN_KEY ) && ( t.parent == parentIndex ) )
mercurywaters 3:fab591fca1e7 71 {
mercurywaters 3:fab591fca1e7 72 size_t keyLength = (size_t) ( t.end - t.start );
mercurywaters 3:fab591fca1e7 73 if ( ( strlen ( key ) == keyLength ) && ( strncmp ( source + t.start, key, keyLength ) == 0 ) )
mercurywaters 3:fab591fca1e7 74 {
mercurywaters 0:7f4a18b3fd82 75 retVal = i;
mercurywaters 0:7f4a18b3fd82 76 break;
mercurywaters 0:7f4a18b3fd82 77 }
mercurywaters 0:7f4a18b3fd82 78 }
mercurywaters 0:7f4a18b3fd82 79 }
mercurywaters 0:7f4a18b3fd82 80 }
mercurywaters 3:fab591fca1e7 81
mercurywaters 0:7f4a18b3fd82 82 return retVal;
mercurywaters 0:7f4a18b3fd82 83 }
mercurywaters 0:7f4a18b3fd82 84
mercurywaters 0:7f4a18b3fd82 85 int Json::findChildIndexOf ( const int &parentIndex, const int &startingAt ) const
mercurywaters 0:7f4a18b3fd82 86 {
mercurywaters 0:7f4a18b3fd82 87 int retVal = -1;
mercurywaters 3:fab591fca1e7 88
mercurywaters 3:fab591fca1e7 89 if ( parentIndex != -1 && parentIndex < tokenCount )
mercurywaters 3:fab591fca1e7 90 {
mercurywaters 3:fab591fca1e7 91
mercurywaters 0:7f4a18b3fd82 92 jsmntype_t type = tokens [ parentIndex ].type;
mercurywaters 3:fab591fca1e7 93 if ( ( type == JSMN_KEY ) || ( type == JSMN_OBJECT ) || ( type == JSMN_ARRAY ) )
mercurywaters 3:fab591fca1e7 94 {
mercurywaters 0:7f4a18b3fd82 95 int i = startingAt + 1;
mercurywaters 3:fab591fca1e7 96 if ( startingAt < 0 )
mercurywaters 3:fab591fca1e7 97 {
mercurywaters 0:7f4a18b3fd82 98 i = 0;
mercurywaters 0:7f4a18b3fd82 99 }
mercurywaters 3:fab591fca1e7 100
mercurywaters 3:fab591fca1e7 101 for ( ; i < tokenCount; i++ )
mercurywaters 3:fab591fca1e7 102 {
mercurywaters 3:fab591fca1e7 103 if ( tokens [ i ].parent == parentIndex )
mercurywaters 3:fab591fca1e7 104 {
mercurywaters 0:7f4a18b3fd82 105 retVal = i;
mercurywaters 0:7f4a18b3fd82 106 break;
mercurywaters 0:7f4a18b3fd82 107 }
mercurywaters 0:7f4a18b3fd82 108 }
mercurywaters 0:7f4a18b3fd82 109 }
mercurywaters 0:7f4a18b3fd82 110 }
mercurywaters 3:fab591fca1e7 111
mercurywaters 0:7f4a18b3fd82 112 return retVal;
mercurywaters 0:7f4a18b3fd82 113 }
mercurywaters 0:7f4a18b3fd82 114
mercurywaters 0:7f4a18b3fd82 115 bool Json::matches ( const int & tokenIndex, const char * value ) const
mercurywaters 0:7f4a18b3fd82 116 {
mercurywaters 0:7f4a18b3fd82 117 jsmntok_t token = tokens [ tokenIndex ];
mercurywaters 0:7f4a18b3fd82 118 return ( strncmp ( source + token.start, value, ( token.end - token.start ) ) == 0 );
mercurywaters 0:7f4a18b3fd82 119 }
mercurywaters 0:7f4a18b3fd82 120
mercurywaters 3:fab591fca1e7 121 int Json::tokenIntegerValue ( const int tokenIndex ) const
mercurywaters 3:fab591fca1e7 122 {
mercurywaters 3:fab591fca1e7 123 if ( type ( tokenIndex ) == JSMN_PRIMITIVE )
mercurywaters 3:fab591fca1e7 124 {
mercurywaters 3:fab591fca1e7 125 int len = tokenLength ( tokenIndex );
mercurywaters 3:fab591fca1e7 126 char * tok = new char [ len + 1 ];
mercurywaters 3:fab591fca1e7 127 strncpy ( tok, tokenAddress ( tokenIndex ), len );
mercurywaters 3:fab591fca1e7 128 tok [ len ] = 0;
mercurywaters 3:fab591fca1e7 129 int retVal = atoi ( tok );
mercurywaters 3:fab591fca1e7 130 delete [] tok;
mercurywaters 3:fab591fca1e7 131 return retVal;
mercurywaters 3:fab591fca1e7 132 }
mercurywaters 3:fab591fca1e7 133 return -1;
mercurywaters 3:fab591fca1e7 134 }
mercurywaters 3:fab591fca1e7 135
mercurywaters 3:fab591fca1e7 136 float Json::tokenNumberValue ( const int tokenIndex ) const
mercurywaters 0:7f4a18b3fd82 137 {
mercurywaters 3:fab591fca1e7 138 if ( type ( tokenIndex ) == JSMN_PRIMITIVE )
mercurywaters 3:fab591fca1e7 139 {
mercurywaters 3:fab591fca1e7 140 int len = tokenLength ( tokenIndex );
mercurywaters 3:fab591fca1e7 141 char * tok = new char [ len + 1 ];
mercurywaters 3:fab591fca1e7 142 strncpy ( tok, tokenAddress ( tokenIndex ), len );
mercurywaters 3:fab591fca1e7 143 tok [ len ] = 0;
mercurywaters 3:fab591fca1e7 144 float retVal = atof ( tok );
mercurywaters 3:fab591fca1e7 145 delete [] tok;
mercurywaters 3:fab591fca1e7 146 return retVal;
mercurywaters 3:fab591fca1e7 147 }
mercurywaters 3:fab591fca1e7 148 return -1;
mercurywaters 3:fab591fca1e7 149 }
mercurywaters 3:fab591fca1e7 150
mercurywaters 3:fab591fca1e7 151
mercurywaters 3:fab591fca1e7 152 // void Json::print () const
mercurywaters 3:fab591fca1e7 153 // {
mercurywaters 3:fab591fca1e7 154 // #ifdef SOFTWARE_DEBUG
mercurywaters 3:fab591fca1e7 155 // const char * TYPES [] = {
mercurywaters 3:fab591fca1e7 156 // "UNDEFINED",
mercurywaters 3:fab591fca1e7 157 // "OBJECT ",
mercurywaters 3:fab591fca1e7 158 // "ARRAY ",
mercurywaters 3:fab591fca1e7 159 // "STRING ",
mercurywaters 3:fab591fca1e7 160 // "PRIMITIVE",
mercurywaters 3:fab591fca1e7 161 // "KEY "
mercurywaters 3:fab591fca1e7 162 // };
mercurywaters 3:fab591fca1e7 163 //
mercurywaters 3:fab591fca1e7 164 // for ( int i = 0; i < tokenCount; i ++ ) {
mercurywaters 3:fab591fca1e7 165 // debug ( "Index: %3d, Type:%d(%s), Indices: (%3d to %3d), ParentIndex: %3d, ChildCount: %3d Data: %.*s", i, tokens [ i ].type, TYPES [ tokens [ i ].type ], tokens [ i ].start, tokens [ i ].end, tokens [ i ].parent, tokens [ i ].childCount, tokens [ i ].end - tokens [ i ].start, source + tokens [ i ].start );
mercurywaters 3:fab591fca1e7 166 // }
mercurywaters 3:fab591fca1e7 167 // debug ( "" );
mercurywaters 3:fab591fca1e7 168 // #endif
mercurywaters 3:fab591fca1e7 169 // }
mercurywaters 3:fab591fca1e7 170
faheem_chaudhary 4:ae34010d87e5 171 char * Json::unescape ( char * jsonString )
faheem_chaudhary 4:ae34010d87e5 172 {
faheem_chaudhary 4:ae34010d87e5 173 if ( jsonString != NULL )
faheem_chaudhary 4:ae34010d87e5 174 {
faheem_chaudhary 4:ae34010d87e5 175 int stringIndex = 0;
faheem_chaudhary 4:ae34010d87e5 176 int indentLevel = 0;
faheem_chaudhary 4:ae34010d87e5 177 int quoteCount = 0;
faheem_chaudhary 4:ae34010d87e5 178 for ( int i = 0; jsonString [ i ] != 0; i ++ )
faheem_chaudhary 4:ae34010d87e5 179 {
faheem_chaudhary 4:ae34010d87e5 180 switch ( jsonString [ i ] )
faheem_chaudhary 4:ae34010d87e5 181 {
faheem_chaudhary 4:ae34010d87e5 182 case '{':
faheem_chaudhary 4:ae34010d87e5 183 indentLevel ++;
faheem_chaudhary 4:ae34010d87e5 184 break;
faheem_chaudhary 4:ae34010d87e5 185
faheem_chaudhary 4:ae34010d87e5 186 case '}':
faheem_chaudhary 4:ae34010d87e5 187 indentLevel --;
faheem_chaudhary 4:ae34010d87e5 188 if ( indentLevel == 0 ) {
faheem_chaudhary 4:ae34010d87e5 189 // Just close and return the first valid JSON object. No need to handle complex cases.
faheem_chaudhary 4:ae34010d87e5 190 jsonString [ stringIndex ++ ] = '}';
faheem_chaudhary 4:ae34010d87e5 191 jsonString [ stringIndex ] = 0;
faheem_chaudhary 4:ae34010d87e5 192 return jsonString;
faheem_chaudhary 4:ae34010d87e5 193 }
faheem_chaudhary 4:ae34010d87e5 194 break;
faheem_chaudhary 4:ae34010d87e5 195
faheem_chaudhary 4:ae34010d87e5 196 case '\\':
faheem_chaudhary 4:ae34010d87e5 197 i ++;
faheem_chaudhary 4:ae34010d87e5 198 break;
faheem_chaudhary 4:ae34010d87e5 199
faheem_chaudhary 4:ae34010d87e5 200 case '"':
faheem_chaudhary 4:ae34010d87e5 201 quoteCount ++;
faheem_chaudhary 4:ae34010d87e5 202 break;
faheem_chaudhary 4:ae34010d87e5 203 }
faheem_chaudhary 4:ae34010d87e5 204
faheem_chaudhary 4:ae34010d87e5 205 if ( indentLevel > 0 )
faheem_chaudhary 4:ae34010d87e5 206 {
faheem_chaudhary 4:ae34010d87e5 207 if ( quoteCount == 0 ) {
faheem_chaudhary 4:ae34010d87e5 208 return jsonString; //No need to unescape. JsonString needs to be already escaped
faheem_chaudhary 4:ae34010d87e5 209 }
faheem_chaudhary 4:ae34010d87e5 210 jsonString [ stringIndex ++ ] = jsonString [ i ];
faheem_chaudhary 4:ae34010d87e5 211 }
faheem_chaudhary 4:ae34010d87e5 212 }
faheem_chaudhary 4:ae34010d87e5 213 jsonString [ stringIndex ] = 0;
faheem_chaudhary 4:ae34010d87e5 214 }
faheem_chaudhary 4:ae34010d87e5 215
faheem_chaudhary 4:ae34010d87e5 216 return jsonString;
faheem_chaudhary 4:ae34010d87e5 217 }