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 16 22:26:36 2016 +0000
Revision:
7:8aa4d0e98eb0
Parent:
5:dd98cf00ed9b
Added a very basic example in documentation

Who changed what in which revision?

UserRevisionLine numberNew contents of line
faheem_chaudhary 5:dd98cf00ed9b 1 /* Json.cpp */
faheem_chaudhary 5:dd98cf00ed9b 2 /* Original Author: Faheem Inayat
faheem_chaudhary 5:dd98cf00ed9b 3 * Created by "Night Crue" Team @ TechShop San Jose, CA
faheem_chaudhary 5:dd98cf00ed9b 4 *
faheem_chaudhary 5:dd98cf00ed9b 5 * MIT License
faheem_chaudhary 5:dd98cf00ed9b 6 *
faheem_chaudhary 5:dd98cf00ed9b 7 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
faheem_chaudhary 5:dd98cf00ed9b 8 * and associated documentation files (the "Software"), to deal in the Software without restriction,
faheem_chaudhary 5:dd98cf00ed9b 9 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
faheem_chaudhary 5:dd98cf00ed9b 10 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
faheem_chaudhary 5:dd98cf00ed9b 11 * furnished to do so, subject to the following conditions:
faheem_chaudhary 5:dd98cf00ed9b 12 *
faheem_chaudhary 5:dd98cf00ed9b 13 * The above copyright notice and this permission notice shall be included in all copies or
faheem_chaudhary 5:dd98cf00ed9b 14 * substantial portions of the Software.
faheem_chaudhary 5:dd98cf00ed9b 15 *
faheem_chaudhary 5:dd98cf00ed9b 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
faheem_chaudhary 5:dd98cf00ed9b 17 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
faheem_chaudhary 5:dd98cf00ed9b 18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
faheem_chaudhary 5:dd98cf00ed9b 19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
faheem_chaudhary 5:dd98cf00ed9b 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
faheem_chaudhary 5:dd98cf00ed9b 21 */
faheem_chaudhary 5:dd98cf00ed9b 22
mercurywaters 0:7f4a18b3fd82 23 #include "Json.h"
mercurywaters 0:7f4a18b3fd82 24
faheem_chaudhary 5:dd98cf00ed9b 25 Json::Json ( const char * jsonString, size_t length, unsigned int maxTokens )
faheem_chaudhary 5:dd98cf00ed9b 26 : maxTokenCount ( maxTokens ), source ( jsonString ), sourceLength ( length )
mercurywaters 0:7f4a18b3fd82 27 {
mercurywaters 0:7f4a18b3fd82 28 jsmn_parser parser;
faheem_chaudhary 5:dd98cf00ed9b 29 tokens = new jsmntok_t [ maxTokenCount ];
mercurywaters 3:fab591fca1e7 30
mercurywaters 0:7f4a18b3fd82 31 jsmn_init ( &parser );
faheem_chaudhary 5:dd98cf00ed9b 32 tokenCount = jsmn_parse ( &parser, jsonString, length, tokens, maxTokenCount );
mercurywaters 0:7f4a18b3fd82 33 }
mercurywaters 0:7f4a18b3fd82 34
faheem_chaudhary 5:dd98cf00ed9b 35 Json::Json ( const Json & )
faheem_chaudhary 5:dd98cf00ed9b 36 : maxTokenCount ( 0 ), source ( NULL ), sourceLength ( 0 )
mercurywaters 3:fab591fca1e7 37 {
mercurywaters 3:fab591fca1e7 38 tokenCount = 0;
mercurywaters 3:fab591fca1e7 39 tokens = NULL;
mercurywaters 3:fab591fca1e7 40 }
mercurywaters 3:fab591fca1e7 41
mercurywaters 3:fab591fca1e7 42 Json::~Json ()
mercurywaters 0:7f4a18b3fd82 43 {
mercurywaters 0:7f4a18b3fd82 44 delete [] tokens;
mercurywaters 0:7f4a18b3fd82 45 }
mercurywaters 0:7f4a18b3fd82 46
faheem_chaudhary 4:ae34010d87e5 47 int Json::findKeyIndex ( const char * key, const int &startingAt ) const
faheem_chaudhary 4:ae34010d87e5 48 {
faheem_chaudhary 4:ae34010d87e5 49 int retVal = -1;
faheem_chaudhary 4:ae34010d87e5 50
faheem_chaudhary 4:ae34010d87e5 51 int i = startingAt + 1;
faheem_chaudhary 4:ae34010d87e5 52 if ( i < 0 ) {
faheem_chaudhary 4:ae34010d87e5 53 i = 0;
faheem_chaudhary 4:ae34010d87e5 54 }
faheem_chaudhary 4:ae34010d87e5 55
faheem_chaudhary 4:ae34010d87e5 56 for ( ; i < tokenCount; i++ )
faheem_chaudhary 4:ae34010d87e5 57 {
faheem_chaudhary 4:ae34010d87e5 58 jsmntok_t t = tokens [ i ];
faheem_chaudhary 4:ae34010d87e5 59
faheem_chaudhary 4:ae34010d87e5 60 if ( t.type == JSMN_KEY )
faheem_chaudhary 4:ae34010d87e5 61 {
faheem_chaudhary 4:ae34010d87e5 62 size_t keyLength = (size_t) ( t.end - t.start );
faheem_chaudhary 4:ae34010d87e5 63 if ( ( strlen ( key ) == keyLength ) && ( strncmp ( source + t.start, key, keyLength ) == 0 ) )
faheem_chaudhary 4:ae34010d87e5 64 {
faheem_chaudhary 4:ae34010d87e5 65 retVal = i;
faheem_chaudhary 4:ae34010d87e5 66 break;
faheem_chaudhary 4:ae34010d87e5 67 }
faheem_chaudhary 4:ae34010d87e5 68 }
faheem_chaudhary 4:ae34010d87e5 69 }
faheem_chaudhary 4:ae34010d87e5 70
faheem_chaudhary 4:ae34010d87e5 71 return retVal;
faheem_chaudhary 4:ae34010d87e5 72 }
faheem_chaudhary 4:ae34010d87e5 73
mercurywaters 0:7f4a18b3fd82 74 int Json::findKeyIndexIn ( const char * key, const int &parentIndex ) const
mercurywaters 0:7f4a18b3fd82 75 {
mercurywaters 0:7f4a18b3fd82 76 int retVal = -1;
mercurywaters 3:fab591fca1e7 77
faheem_chaudhary 5:dd98cf00ed9b 78 if ( isValidToken ( parentIndex ) )
mercurywaters 3:fab591fca1e7 79 {
mercurywaters 3:fab591fca1e7 80 for ( int i = parentIndex + 1; i < tokenCount; i++ )
mercurywaters 3:fab591fca1e7 81 {
mercurywaters 0:7f4a18b3fd82 82 jsmntok_t t = tokens [ i ];
mercurywaters 3:fab591fca1e7 83
mercurywaters 3:fab591fca1e7 84 if ( t.end >= tokens [ parentIndex ].end )
mercurywaters 3:fab591fca1e7 85 {
mercurywaters 0:7f4a18b3fd82 86 break;
mercurywaters 0:7f4a18b3fd82 87 }
mercurywaters 3:fab591fca1e7 88
mercurywaters 3:fab591fca1e7 89 if ( ( t.type == JSMN_KEY ) && ( t.parent == parentIndex ) )
mercurywaters 3:fab591fca1e7 90 {
mercurywaters 3:fab591fca1e7 91 size_t keyLength = (size_t) ( t.end - t.start );
mercurywaters 3:fab591fca1e7 92 if ( ( strlen ( key ) == keyLength ) && ( strncmp ( source + t.start, key, keyLength ) == 0 ) )
mercurywaters 3:fab591fca1e7 93 {
mercurywaters 0:7f4a18b3fd82 94 retVal = i;
mercurywaters 0:7f4a18b3fd82 95 break;
mercurywaters 0:7f4a18b3fd82 96 }
mercurywaters 0:7f4a18b3fd82 97 }
mercurywaters 0:7f4a18b3fd82 98 }
mercurywaters 0:7f4a18b3fd82 99 }
mercurywaters 3:fab591fca1e7 100
mercurywaters 0:7f4a18b3fd82 101 return retVal;
mercurywaters 0:7f4a18b3fd82 102 }
mercurywaters 0:7f4a18b3fd82 103
mercurywaters 0:7f4a18b3fd82 104 int Json::findChildIndexOf ( const int &parentIndex, const int &startingAt ) const
mercurywaters 0:7f4a18b3fd82 105 {
mercurywaters 0:7f4a18b3fd82 106 int retVal = -1;
mercurywaters 3:fab591fca1e7 107
faheem_chaudhary 5:dd98cf00ed9b 108 if ( isValidToken ( parentIndex ) )
mercurywaters 3:fab591fca1e7 109 {
mercurywaters 3:fab591fca1e7 110
mercurywaters 0:7f4a18b3fd82 111 jsmntype_t type = tokens [ parentIndex ].type;
mercurywaters 3:fab591fca1e7 112 if ( ( type == JSMN_KEY ) || ( type == JSMN_OBJECT ) || ( type == JSMN_ARRAY ) )
mercurywaters 3:fab591fca1e7 113 {
mercurywaters 0:7f4a18b3fd82 114 int i = startingAt + 1;
mercurywaters 3:fab591fca1e7 115 if ( startingAt < 0 )
mercurywaters 3:fab591fca1e7 116 {
mercurywaters 0:7f4a18b3fd82 117 i = 0;
mercurywaters 0:7f4a18b3fd82 118 }
mercurywaters 3:fab591fca1e7 119
faheem_chaudhary 5:dd98cf00ed9b 120 for ( i += parentIndex; i < tokenCount; i++ )
mercurywaters 3:fab591fca1e7 121 {
mercurywaters 3:fab591fca1e7 122 if ( tokens [ i ].parent == parentIndex )
mercurywaters 3:fab591fca1e7 123 {
mercurywaters 0:7f4a18b3fd82 124 retVal = i;
mercurywaters 0:7f4a18b3fd82 125 break;
mercurywaters 0:7f4a18b3fd82 126 }
mercurywaters 0:7f4a18b3fd82 127 }
mercurywaters 0:7f4a18b3fd82 128 }
mercurywaters 0:7f4a18b3fd82 129 }
mercurywaters 3:fab591fca1e7 130
mercurywaters 0:7f4a18b3fd82 131 return retVal;
mercurywaters 0:7f4a18b3fd82 132 }
mercurywaters 0:7f4a18b3fd82 133
mercurywaters 0:7f4a18b3fd82 134 bool Json::matches ( const int & tokenIndex, const char * value ) const
mercurywaters 0:7f4a18b3fd82 135 {
faheem_chaudhary 5:dd98cf00ed9b 136 bool retVal = false;
faheem_chaudhary 5:dd98cf00ed9b 137
faheem_chaudhary 5:dd98cf00ed9b 138 if ( isValidToken ( tokenIndex ) )
faheem_chaudhary 5:dd98cf00ed9b 139 {
faheem_chaudhary 5:dd98cf00ed9b 140 jsmntok_t token = tokens [ tokenIndex ];
faheem_chaudhary 5:dd98cf00ed9b 141 retVal = ( strncmp ( source + token.start, value, ( token.end - token.start ) ) == 0 );
faheem_chaudhary 5:dd98cf00ed9b 142 }
faheem_chaudhary 5:dd98cf00ed9b 143
faheem_chaudhary 5:dd98cf00ed9b 144 return retVal;
mercurywaters 0:7f4a18b3fd82 145 }
mercurywaters 0:7f4a18b3fd82 146
faheem_chaudhary 5:dd98cf00ed9b 147 int Json::tokenIntegerValue ( const int tokenIndex, int &returnValue ) const
mercurywaters 3:fab591fca1e7 148 {
faheem_chaudhary 5:dd98cf00ed9b 149 int retVal = -1;
faheem_chaudhary 5:dd98cf00ed9b 150
mercurywaters 3:fab591fca1e7 151 if ( type ( tokenIndex ) == JSMN_PRIMITIVE )
mercurywaters 3:fab591fca1e7 152 {
mercurywaters 3:fab591fca1e7 153 int len = tokenLength ( tokenIndex );
mercurywaters 3:fab591fca1e7 154 char * tok = new char [ len + 1 ];
mercurywaters 3:fab591fca1e7 155 strncpy ( tok, tokenAddress ( tokenIndex ), len );
mercurywaters 3:fab591fca1e7 156 tok [ len ] = 0;
faheem_chaudhary 5:dd98cf00ed9b 157 returnValue = atoi ( tok );
mercurywaters 3:fab591fca1e7 158 delete [] tok;
faheem_chaudhary 5:dd98cf00ed9b 159 retVal = 0;
mercurywaters 3:fab591fca1e7 160 }
faheem_chaudhary 5:dd98cf00ed9b 161 return retVal;
mercurywaters 3:fab591fca1e7 162 }
mercurywaters 3:fab591fca1e7 163
faheem_chaudhary 5:dd98cf00ed9b 164 int Json::tokenNumberValue ( const int tokenIndex, float &returnValue ) const
faheem_chaudhary 5:dd98cf00ed9b 165 {
faheem_chaudhary 5:dd98cf00ed9b 166 int retVal = -1;
faheem_chaudhary 5:dd98cf00ed9b 167
faheem_chaudhary 5:dd98cf00ed9b 168 if ( type ( tokenIndex ) == JSMN_PRIMITIVE )
faheem_chaudhary 5:dd98cf00ed9b 169 {
faheem_chaudhary 5:dd98cf00ed9b 170 int len = tokenLength ( tokenIndex );
faheem_chaudhary 5:dd98cf00ed9b 171 char * tok = new char [ len + 1 ];
faheem_chaudhary 5:dd98cf00ed9b 172 strncpy ( tok, tokenAddress ( tokenIndex ), len );
faheem_chaudhary 5:dd98cf00ed9b 173 tok [ len ] = 0;
faheem_chaudhary 5:dd98cf00ed9b 174 returnValue = atof ( tok );
faheem_chaudhary 5:dd98cf00ed9b 175 delete [] tok;
faheem_chaudhary 5:dd98cf00ed9b 176 retVal = 0;
faheem_chaudhary 5:dd98cf00ed9b 177 }
faheem_chaudhary 5:dd98cf00ed9b 178
faheem_chaudhary 5:dd98cf00ed9b 179 return retVal;
faheem_chaudhary 5:dd98cf00ed9b 180 }
mercurywaters 3:fab591fca1e7 181
faheem_chaudhary 5:dd98cf00ed9b 182 int Json::tokenBooleanValue ( const int tokenIndex, bool &returnValue ) const
faheem_chaudhary 5:dd98cf00ed9b 183 {
faheem_chaudhary 5:dd98cf00ed9b 184 int retVal = -1;
faheem_chaudhary 5:dd98cf00ed9b 185
faheem_chaudhary 5:dd98cf00ed9b 186 if ( type ( tokenIndex ) == JSMN_PRIMITIVE )
faheem_chaudhary 5:dd98cf00ed9b 187 {
faheem_chaudhary 5:dd98cf00ed9b 188 returnValue = matches ( tokenIndex, "true" );
faheem_chaudhary 5:dd98cf00ed9b 189 retVal = 0;
faheem_chaudhary 5:dd98cf00ed9b 190 }
faheem_chaudhary 5:dd98cf00ed9b 191
faheem_chaudhary 5:dd98cf00ed9b 192 return retVal;
faheem_chaudhary 5:dd98cf00ed9b 193 }
mercurywaters 3:fab591fca1e7 194
faheem_chaudhary 4:ae34010d87e5 195 char * Json::unescape ( char * jsonString )
faheem_chaudhary 4:ae34010d87e5 196 {
faheem_chaudhary 4:ae34010d87e5 197 if ( jsonString != NULL )
faheem_chaudhary 4:ae34010d87e5 198 {
faheem_chaudhary 4:ae34010d87e5 199 int stringIndex = 0;
faheem_chaudhary 4:ae34010d87e5 200 int indentLevel = 0;
faheem_chaudhary 4:ae34010d87e5 201 int quoteCount = 0;
faheem_chaudhary 4:ae34010d87e5 202 for ( int i = 0; jsonString [ i ] != 0; i ++ )
faheem_chaudhary 4:ae34010d87e5 203 {
faheem_chaudhary 4:ae34010d87e5 204 switch ( jsonString [ i ] )
faheem_chaudhary 4:ae34010d87e5 205 {
faheem_chaudhary 4:ae34010d87e5 206 case '{':
faheem_chaudhary 4:ae34010d87e5 207 indentLevel ++;
faheem_chaudhary 4:ae34010d87e5 208 break;
faheem_chaudhary 4:ae34010d87e5 209
faheem_chaudhary 4:ae34010d87e5 210 case '}':
faheem_chaudhary 4:ae34010d87e5 211 indentLevel --;
faheem_chaudhary 4:ae34010d87e5 212 if ( indentLevel == 0 ) {
faheem_chaudhary 4:ae34010d87e5 213 // Just close and return the first valid JSON object. No need to handle complex cases.
faheem_chaudhary 4:ae34010d87e5 214 jsonString [ stringIndex ++ ] = '}';
faheem_chaudhary 4:ae34010d87e5 215 jsonString [ stringIndex ] = 0;
faheem_chaudhary 4:ae34010d87e5 216 return jsonString;
faheem_chaudhary 4:ae34010d87e5 217 }
faheem_chaudhary 4:ae34010d87e5 218 break;
faheem_chaudhary 4:ae34010d87e5 219
faheem_chaudhary 4:ae34010d87e5 220 case '\\':
faheem_chaudhary 4:ae34010d87e5 221 i ++;
faheem_chaudhary 4:ae34010d87e5 222 break;
faheem_chaudhary 4:ae34010d87e5 223
faheem_chaudhary 4:ae34010d87e5 224 case '"':
faheem_chaudhary 4:ae34010d87e5 225 quoteCount ++;
faheem_chaudhary 4:ae34010d87e5 226 break;
faheem_chaudhary 4:ae34010d87e5 227 }
faheem_chaudhary 4:ae34010d87e5 228
faheem_chaudhary 4:ae34010d87e5 229 if ( indentLevel > 0 )
faheem_chaudhary 4:ae34010d87e5 230 {
faheem_chaudhary 4:ae34010d87e5 231 if ( quoteCount == 0 ) {
faheem_chaudhary 4:ae34010d87e5 232 return jsonString; //No need to unescape. JsonString needs to be already escaped
faheem_chaudhary 4:ae34010d87e5 233 }
faheem_chaudhary 4:ae34010d87e5 234 jsonString [ stringIndex ++ ] = jsonString [ i ];
faheem_chaudhary 4:ae34010d87e5 235 }
faheem_chaudhary 4:ae34010d87e5 236 }
faheem_chaudhary 4:ae34010d87e5 237 jsonString [ stringIndex ] = 0;
faheem_chaudhary 4:ae34010d87e5 238 }
faheem_chaudhary 4:ae34010d87e5 239
faheem_chaudhary 4:ae34010d87e5 240 return jsonString;
faheem_chaudhary 4:ae34010d87e5 241 }