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:
6:c1d2153da4ed
Added a very basic example in documentation

Who changed what in which revision?

UserRevisionLine numberNew contents of line
faheem_chaudhary 5:dd98cf00ed9b 1 /* Json.h */
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 3:fab591fca1e7 23 #ifndef __JSON_LIB_CLASS_H_
mercurywaters 3:fab591fca1e7 24 #define __JSON_LIB_CLASS_H_
mercurywaters 3:fab591fca1e7 25
mercurywaters 3:fab591fca1e7 26 #include "jsmn.h"
mercurywaters 3:fab591fca1e7 27 #include <stdlib.h>
mercurywaters 3:fab591fca1e7 28 #include <string.h>
mercurywaters 3:fab591fca1e7 29
mercurywaters 3:fab591fca1e7 30 /**
faheem_chaudhary 5:dd98cf00ed9b 31 * C++ JSON wrapper over JSMN lib (https://github.com/zserge/jsmn).
faheem_chaudhary 5:dd98cf00ed9b 32 *
faheem_chaudhary 5:dd98cf00ed9b 33 * This C++ Class is a set of common tools/procedures as a C++ wrapper over JSMN
faheem_chaudhary 5:dd98cf00ed9b 34 * JSON parser library. It is intended to provide the boiler-plate code, with
faheem_chaudhary 5:dd98cf00ed9b 35 * intentions to reduce code clutter, in more of C++ fashion.
faheem_chaudhary 5:dd98cf00ed9b 36 *
faheem_chaudhary 5:dd98cf00ed9b 37 * In contrast to original library, Json is intended to work strictly with valid
faheem_chaudhary 5:dd98cf00ed9b 38 * JSON structures. Non-standard JSON structures should result in an error.
faheem_chaudhary 5:dd98cf00ed9b 39 *
faheem_chaudhary 5:dd98cf00ed9b 40 * This class works explicitly on the indices returned by underlying JSMN
faheem_chaudhary 5:dd98cf00ed9b 41 * library. In the scope of this class, its function parameters, return types,
faheem_chaudhary 5:dd98cf00ed9b 42 * and documentation, the term 'index' will always mean the index of JSMN
faheem_chaudhary 5:dd98cf00ed9b 43 * tokens, parsed by the Json constructor, unless and until explicitly mentioned
faheem_chaudhary 5:dd98cf00ed9b 44 * otherwise.
mercurywaters 3:fab591fca1e7 45 */
faheem_chaudhary 7:8aa4d0e98eb0 46
faheem_chaudhary 7:8aa4d0e98eb0 47 /*
faheem_chaudhary 7:8aa4d0e98eb0 48 Example:
faheem_chaudhary 7:8aa4d0e98eb0 49
faheem_chaudhary 7:8aa4d0e98eb0 50 Let's say we have to parse the samle JSON:
faheem_chaudhary 7:8aa4d0e98eb0 51
faheem_chaudhary 7:8aa4d0e98eb0 52 {
faheem_chaudhary 7:8aa4d0e98eb0 53 "team": "Night Crue",
faheem_chaudhary 7:8aa4d0e98eb0 54 "company": "TechShop",
faheem_chaudhary 7:8aa4d0e98eb0 55 "city": "San Jose",
faheem_chaudhary 7:8aa4d0e98eb0 56 "state": "California",
faheem_chaudhary 7:8aa4d0e98eb0 57 "country": "USA",
faheem_chaudhary 7:8aa4d0e98eb0 58 "zip": 95113,
faheem_chaudhary 7:8aa4d0e98eb0 59 "active": true,
faheem_chaudhary 7:8aa4d0e98eb0 60 "members":
faheem_chaudhary 7:8aa4d0e98eb0 61 [
faheem_chaudhary 7:8aa4d0e98eb0 62 {
faheem_chaudhary 7:8aa4d0e98eb0 63 "firstName": "John",
faheem_chaudhary 7:8aa4d0e98eb0 64 "lastName": "Smith",
faheem_chaudhary 7:8aa4d0e98eb0 65 "active": false,
faheem_chaudhary 7:8aa4d0e98eb0 66 "hours": 18.5,
faheem_chaudhary 7:8aa4d0e98eb0 67 "age": 21
faheem_chaudhary 7:8aa4d0e98eb0 68 },
faheem_chaudhary 7:8aa4d0e98eb0 69 {
faheem_chaudhary 7:8aa4d0e98eb0 70 "firstName": "Foo",
faheem_chaudhary 7:8aa4d0e98eb0 71 "lastName": "Bar",
faheem_chaudhary 7:8aa4d0e98eb0 72 "active": true,
faheem_chaudhary 7:8aa4d0e98eb0 73 "hours": 25,
faheem_chaudhary 7:8aa4d0e98eb0 74 "age": 21
faheem_chaudhary 7:8aa4d0e98eb0 75 },
faheem_chaudhary 7:8aa4d0e98eb0 76 {
faheem_chaudhary 7:8aa4d0e98eb0 77 "firstName": "Peter",
faheem_chaudhary 7:8aa4d0e98eb0 78 "lastName": "Jones",
faheem_chaudhary 7:8aa4d0e98eb0 79 "active": false
faheem_chaudhary 7:8aa4d0e98eb0 80 }
faheem_chaudhary 7:8aa4d0e98eb0 81 ]
faheem_chaudhary 7:8aa4d0e98eb0 82 }
faheem_chaudhary 7:8aa4d0e98eb0 83
faheem_chaudhary 7:8aa4d0e98eb0 84 which without the "white spaces" will look like: {"team":"Night Crue","company":"TechShop","city":"San Jose","state":"California","country":"USA","zip":95113,"active":true,"members":[{"firstName":"John","lastName":"Smith","active":false,"hours":18.5,"age":21},{"firstName":"Foo","lastName":"Bar","active":true,"hours":25,"age":21},{"firstName":"Peter","lastName":"Jones","active":false}]}
faheem_chaudhary 7:8aa4d0e98eb0 85
faheem_chaudhary 7:8aa4d0e98eb0 86 Anyways, this class doesn't care about the formatting of JSON, however, it
faheem_chaudhary 7:8aa4d0e98eb0 87 DOES care about the validity of JSON. So here's a sample code to parse and
faheem_chaudhary 7:8aa4d0e98eb0 88 extract values from this JSON structure.
faheem_chaudhary 7:8aa4d0e98eb0 89
faheem_chaudhary 7:8aa4d0e98eb0 90 @code
faheem_chaudhary 7:8aa4d0e98eb0 91
faheem_chaudhary 7:8aa4d0e98eb0 92 void main ()
faheem_chaudhary 7:8aa4d0e98eb0 93 {
faheem_chaudhary 7:8aa4d0e98eb0 94 // Note that the JSON object is 'escaped'. One doesn't get escaped JSON
faheem_chaudhary 7:8aa4d0e98eb0 95 // directly from the webservice, if the response type is APPLICATION/JSON
faheem_chaudhary 7:8aa4d0e98eb0 96 // Just a little thing to keep in mind.
faheem_chaudhary 7:8aa4d0e98eb0 97 const char * jsonSource = "{\"team\":\"Night Crue\",\"company\":\"TechShop\",\"city\":\"San Jose\",\"state\":\"California\",\"country\":\"USA\",\"zip\":95113,\"active\":true,\"members\":[{\"firstName\":\"John\",\"lastName\":\"Smith\",\"active\":false,\"hours\":18.5,\"age\":21},{\"firstName\":\"Foo\",\"lastName\":\"Bar\",\"active\":true,\"hours\":25,\"age\":21},{\"firstName\":\"Peter\",\"lastName\":\"Jones\",\"active\":false}]}";
faheem_chaudhary 7:8aa4d0e98eb0 98
faheem_chaudhary 7:8aa4d0e98eb0 99 Json json ( jsonSource, strlen ( jsonSource ) );
faheem_chaudhary 7:8aa4d0e98eb0 100
faheem_chaudhary 7:8aa4d0e98eb0 101 if ( !json.isValidJson () )
faheem_chaudhary 7:8aa4d0e98eb0 102 {
faheem_chaudhary 7:8aa4d0e98eb0 103 logError ( "Invalid JSON: %s", jsonSource );
faheem_chaudhary 7:8aa4d0e98eb0 104 return;
faheem_chaudhary 7:8aa4d0e98eb0 105 }
faheem_chaudhary 7:8aa4d0e98eb0 106
faheem_chaudhary 7:8aa4d0e98eb0 107 if ( json.type (0) != JSMN_OBJECT )
faheem_chaudhary 7:8aa4d0e98eb0 108 {
faheem_chaudhary 7:8aa4d0e98eb0 109 logError ( "Invalid JSON. ROOT element is not Object: %s", jsonSource );
faheem_chaudhary 7:8aa4d0e98eb0 110 return;
faheem_chaudhary 7:8aa4d0e98eb0 111 }
faheem_chaudhary 7:8aa4d0e98eb0 112
faheem_chaudhary 7:8aa4d0e98eb0 113 // Let's get the value of key "city" in ROOT object, and copy into
faheem_chaudhary 7:8aa4d0e98eb0 114 // cityValue
faheem_chaudhary 7:8aa4d0e98eb0 115 char cityValue [ 32 ];
faheem_chaudhary 7:8aa4d0e98eb0 116
faheem_chaudhary 7:8aa4d0e98eb0 117 logInfo ( "Finding \"city\" Key ... " );
faheem_chaudhary 7:8aa4d0e98eb0 118 // ROOT object should have '0' tokenIndex, and -1 parentIndex
faheem_chaudhary 7:8aa4d0e98eb0 119 int cityKeyIndex = json.findKeyIndexIn ( "city", 0 );
faheem_chaudhary 7:8aa4d0e98eb0 120 if ( cityKeyIndex == -1 )
faheem_chaudhary 7:8aa4d0e98eb0 121 {
faheem_chaudhary 7:8aa4d0e98eb0 122 // Error handling part ...
faheem_chaudhary 7:8aa4d0e98eb0 123 logError ( "\"city\" does not exist ... do something!!" );
faheem_chaudhary 7:8aa4d0e98eb0 124 }
faheem_chaudhary 7:8aa4d0e98eb0 125 else
faheem_chaudhary 7:8aa4d0e98eb0 126 {
faheem_chaudhary 7:8aa4d0e98eb0 127 // Find the first child index of key-node "city"
faheem_chaudhary 7:8aa4d0e98eb0 128 int cityValueIndex = json.findChildIndexOf ( cityKeyIndex, -1 );
faheem_chaudhary 7:8aa4d0e98eb0 129 if ( cityValueIndex > 0 )
faheem_chaudhary 7:8aa4d0e98eb0 130 {
faheem_chaudhary 7:8aa4d0e98eb0 131 const char * valueStart = json.tokenAddress ( cityValueIndex );
faheem_chaudhary 7:8aa4d0e98eb0 132 int valueLength = json.tokenLength ( cityValueIndex );
faheem_chaudhary 7:8aa4d0e98eb0 133 strncpy ( cityValue, valueStart, valueLength );
faheem_chaudhary 7:8aa4d0e98eb0 134 cityValue [ valueLength ] = 0; // NULL-terminate the string
faheem_chaudhary 7:8aa4d0e98eb0 135
faheem_chaudhary 7:8aa4d0e98eb0 136 //let's print the value. It should be "San Jose"
faheem_chaudhary 7:8aa4d0e98eb0 137 logInfo ( "city: %s", cityValue );
faheem_chaudhary 7:8aa4d0e98eb0 138 }
faheem_chaudhary 7:8aa4d0e98eb0 139 }
faheem_chaudhary 7:8aa4d0e98eb0 140
faheem_chaudhary 7:8aa4d0e98eb0 141 // More on this example to come, later.
faheem_chaudhary 7:8aa4d0e98eb0 142 }
faheem_chaudhary 7:8aa4d0e98eb0 143
faheem_chaudhary 7:8aa4d0e98eb0 144 @endcode
faheem_chaudhary 7:8aa4d0e98eb0 145 */
mercurywaters 3:fab591fca1e7 146
mercurywaters 3:fab591fca1e7 147 class Json
mercurywaters 3:fab591fca1e7 148 {
mercurywaters 3:fab591fca1e7 149 private:
faheem_chaudhary 5:dd98cf00ed9b 150 const unsigned int maxTokenCount;
mercurywaters 3:fab591fca1e7 151 const char * source;
mercurywaters 3:fab591fca1e7 152 const size_t sourceLength;
mercurywaters 3:fab591fca1e7 153 jsmntok_t * tokens;
mercurywaters 3:fab591fca1e7 154 int tokenCount;
faheem_chaudhary 5:dd98cf00ed9b 155
faheem_chaudhary 5:dd98cf00ed9b 156 // Copy COntructor is intentionally kept private to enforce the caller
faheem_chaudhary 5:dd98cf00ed9b 157 // to use pointers/reference, and never pass-by-value
faheem_chaudhary 5:dd98cf00ed9b 158 Json ( const Json & );
mercurywaters 3:fab591fca1e7 159
mercurywaters 3:fab591fca1e7 160 public:
faheem_chaudhary 5:dd98cf00ed9b 161 /** The only constructor allowed.
faheem_chaudhary 5:dd98cf00ed9b 162 As JSON object will create/allocate memory for its working, in favor of
faheem_chaudhary 5:dd98cf00ed9b 163 small memory footprints, it is not allowed to be passed-by-value. So
faheem_chaudhary 5:dd98cf00ed9b 164 there is no copy- or default-constructor
faheem_chaudhary 5:dd98cf00ed9b 165
faheem_chaudhary 6:c1d2153da4ed 166 @param jsonString char string containing JSON data
faheem_chaudhary 6:c1d2153da4ed 167 @param length length of the jsonString
faheem_chaudhary 6:c1d2153da4ed 168 @param maxTokens optional maximum count of Tokens. Default is 32.
mercurywaters 3:fab591fca1e7 169 */
faheem_chaudhary 5:dd98cf00ed9b 170 Json ( const char * jsonString, size_t length, unsigned int maxTokens = 32 );
faheem_chaudhary 5:dd98cf00ed9b 171
faheem_chaudhary 5:dd98cf00ed9b 172
faheem_chaudhary 5:dd98cf00ed9b 173 /** Although there is no virtual function to this class, destructor is
faheem_chaudhary 5:dd98cf00ed9b 174 still made virtual, for just-in-case use. Destructor will delete the
faheem_chaudhary 5:dd98cf00ed9b 175 'tokens' array, created in constructor.
faheem_chaudhary 5:dd98cf00ed9b 176 */
mercurywaters 3:fab591fca1e7 177 virtual ~Json ();
mercurywaters 3:fab591fca1e7 178
faheem_chaudhary 5:dd98cf00ed9b 179
faheem_chaudhary 5:dd98cf00ed9b 180 /** findKeyIndex will find and return the token index representing the
faheem_chaudhary 5:dd98cf00ed9b 181 'Key' in underlying JSON object. It is a strictly a linear key search
faheem_chaudhary 5:dd98cf00ed9b 182 and will return the first occurrence, without the JSON node structure
faheem_chaudhary 5:dd98cf00ed9b 183 semantics. For search in a specific node, refer to #findKeyIndex
faheem_chaudhary 5:dd98cf00ed9b 184
faheem_chaudhary 5:dd98cf00ed9b 185 @param key a char string to find as a 'Key' in JSON structure.
faheem_chaudhary 5:dd98cf00ed9b 186 @param startingAt the starting token-index for 'key' search. The
faheem_chaudhary 5:dd98cf00ed9b 187 search will NOT include this index, but instead will use the
faheem_chaudhary 5:dd98cf00ed9b 188 next one as the starting point. In case, a negative value is
faheem_chaudhary 5:dd98cf00ed9b 189 passed, search will start from '0'. It's caller's
faheem_chaudhary 5:dd98cf00ed9b 190 responsibility to make sure what values they're passing.
faheem_chaudhary 5:dd98cf00ed9b 191 Default value is set to '0', as the zero-th token index in any
faheem_chaudhary 5:dd98cf00ed9b 192 valid JSON object should always be starting object brace '{'.
faheem_chaudhary 5:dd98cf00ed9b 193 So default behavior is to always find the very first occurrence
faheem_chaudhary 5:dd98cf00ed9b 194 of key as represented by 'key' parameter.
faheem_chaudhary 5:dd98cf00ed9b 195
faheem_chaudhary 5:dd98cf00ed9b 196 @return a non-zero positive integer, if a key is found in the source
faheem_chaudhary 5:dd98cf00ed9b 197 JSON. If no key is found, -1 will be returned. There should be
faheem_chaudhary 5:dd98cf00ed9b 198 no '0' value returned in any valid case.
faheem_chaudhary 5:dd98cf00ed9b 199 */
faheem_chaudhary 5:dd98cf00ed9b 200 int findKeyIndex ( const char * key, const int &startingAt = 0 ) const;
faheem_chaudhary 5:dd98cf00ed9b 201
faheem_chaudhary 5:dd98cf00ed9b 202
faheem_chaudhary 5:dd98cf00ed9b 203 /** findKeyIndexIn will find and return the token index representing the
faheem_chaudhary 5:dd98cf00ed9b 204 'Key' in underlying JSON object node. It is strictly a single-level
faheem_chaudhary 5:dd98cf00ed9b 205 key search function, and will NOT look for the key in any child JSON
faheem_chaudhary 5:dd98cf00ed9b 206 nodes (JSON Object/Array).
faheem_chaudhary 5:dd98cf00ed9b 207
faheem_chaudhary 5:dd98cf00ed9b 208 @param key a char string to find as a 'Key' in JSON structure.
faheem_chaudhary 5:dd98cf00ed9b 209 @param parentIndex the starting token-index for 'key' search. The
faheem_chaudhary 5:dd98cf00ed9b 210 search will look for the key, only under the JSON node
faheem_chaudhary 5:dd98cf00ed9b 211 represented by this parentIndex. Default value is '0', making
faheem_chaudhary 5:dd98cf00ed9b 212 the default behavior to look for only root-level keys. The
faheem_chaudhary 5:dd98cf00ed9b 213 valid value range is 0 to [parsedTokenCount()-1] both inclusive.
faheem_chaudhary 5:dd98cf00ed9b 214
faheem_chaudhary 5:dd98cf00ed9b 215 @return a non-zero positive integer, if a key is found in the source
faheem_chaudhary 5:dd98cf00ed9b 216 JSON. If no key is found, -1 will be returned. There should be
faheem_chaudhary 5:dd98cf00ed9b 217 no '0' value returned in any valid case.
faheem_chaudhary 5:dd98cf00ed9b 218 */
faheem_chaudhary 5:dd98cf00ed9b 219 int findKeyIndexIn ( const char * key, const int &parentIndex = 0 ) const;
faheem_chaudhary 5:dd98cf00ed9b 220
faheem_chaudhary 5:dd98cf00ed9b 221
faheem_chaudhary 5:dd98cf00ed9b 222 /** findChildIndexOf will find and return the token index representing
faheem_chaudhary 5:dd98cf00ed9b 223 first child a JSON node represented by parentIndex (that is either a
faheem_chaudhary 5:dd98cf00ed9b 224 Key, an Object, or an Array), and exists after the startingAt value.
faheem_chaudhary 5:dd98cf00ed9b 225 This function is particularly handy in iterating over Array Objects, or
faheem_chaudhary 5:dd98cf00ed9b 226 getting the index for JSON 'Value' of a JSON 'Key'.
faheem_chaudhary 5:dd98cf00ed9b 227
faheem_chaudhary 5:dd98cf00ed9b 228 @param parentIndex token index representing the parent node in JSON
faheem_chaudhary 5:dd98cf00ed9b 229 source. The valid value range is 0 to [parsedTokenCount()-1]
faheem_chaudhary 5:dd98cf00ed9b 230 both inclusive.
faheem_chaudhary 5:dd98cf00ed9b 231 @param startingAt describes the starting index of the nodes to search.
faheem_chaudhary 5:dd98cf00ed9b 232 In other words, if caller wants to skip some nodes, they can
faheem_chaudhary 5:dd98cf00ed9b 233 provide this value. Default value is 0, which means search for
faheem_chaudhary 5:dd98cf00ed9b 234 all nodes in the parent.
faheem_chaudhary 5:dd98cf00ed9b 235
faheem_chaudhary 5:dd98cf00ed9b 236 @return a non-zero positive integer, if the child node is found in
faheem_chaudhary 5:dd98cf00ed9b 237 source JSON. If no child is found, -1 will be returned. There
faheem_chaudhary 5:dd98cf00ed9b 238 should be no '0' value returned in any valid case.
faheem_chaudhary 5:dd98cf00ed9b 239 */
faheem_chaudhary 5:dd98cf00ed9b 240 int findChildIndexOf ( const int &parentIndex, const int &startingAt = 0 ) const;
faheem_chaudhary 5:dd98cf00ed9b 241
faheem_chaudhary 5:dd98cf00ed9b 242
faheem_chaudhary 5:dd98cf00ed9b 243 /** matches will tell if the token data (either key or value) matches
faheem_chaudhary 5:dd98cf00ed9b 244 with the value provided. This function is particularly handy in
faheem_chaudhary 5:dd98cf00ed9b 245 iterating over the keys, and finding a specific key, in an object. The
faheem_chaudhary 5:dd98cf00ed9b 246 comparison is case-sensitive. i.e. 'Apple' will NOT match with 'apple'.
faheem_chaudhary 5:dd98cf00ed9b 247
faheem_chaudhary 5:dd98cf00ed9b 248 @param tokenIndex representing the token to compare. The valid value
faheem_chaudhary 5:dd98cf00ed9b 249 range is 0 to [parsedTokenCount()-1] both inclusive.
faheem_chaudhary 5:dd98cf00ed9b 250 @param value to compare the token data with.
faheem_chaudhary 5:dd98cf00ed9b 251
faheem_chaudhary 5:dd98cf00ed9b 252 @return true if the token data matches with value. false will be
faheem_chaudhary 5:dd98cf00ed9b 253 returned either the value doesn't match OR the tokenIndex is
faheem_chaudhary 5:dd98cf00ed9b 254 not valid.
faheem_chaudhary 5:dd98cf00ed9b 255 */
mercurywaters 3:fab591fca1e7 256 bool matches ( const int & tokenIndex, const char * value ) const;
mercurywaters 3:fab591fca1e7 257
faheem_chaudhary 5:dd98cf00ed9b 258
faheem_chaudhary 5:dd98cf00ed9b 259 /** parsedTokenCount will tell how many tokens have been parsed by JSMN
faheem_chaudhary 5:dd98cf00ed9b 260 parser. It is a utility function, for token validity.
faheem_chaudhary 5:dd98cf00ed9b 261
faheem_chaudhary 5:dd98cf00ed9b 262 @return non-negative integer number of tokens parsed by JSMN library.
faheem_chaudhary 5:dd98cf00ed9b 263 Negative value may be returned in case of error, but this
faheem_chaudhary 5:dd98cf00ed9b 264 behavior is not tested, yet.
faheem_chaudhary 5:dd98cf00ed9b 265 */
faheem_chaudhary 5:dd98cf00ed9b 266 inline int parsedTokenCount () const;
faheem_chaudhary 5:dd98cf00ed9b 267
faheem_chaudhary 5:dd98cf00ed9b 268
faheem_chaudhary 5:dd98cf00ed9b 269 /** isValidJson will tell the caller if the parsed JSON was valid,
faheem_chaudhary 5:dd98cf00ed9b 270 parsed, and accepted to further work on.
faheem_chaudhary 5:dd98cf00ed9b 271
faheem_chaudhary 5:dd98cf00ed9b 272 @return true if the JSON is valid, false otherwise.
faheem_chaudhary 5:dd98cf00ed9b 273 */
mercurywaters 3:fab591fca1e7 274 inline bool isValidJson () const;
faheem_chaudhary 5:dd98cf00ed9b 275
faheem_chaudhary 5:dd98cf00ed9b 276
faheem_chaudhary 5:dd98cf00ed9b 277 /** isValidToken will tell the caller if the tokenIndex is in valid
faheem_chaudhary 5:dd98cf00ed9b 278 range. The valid value range is 0 to [parsedTokenCount()-1] both
faheem_chaudhary 5:dd98cf00ed9b 279 inclusive.
faheem_chaudhary 5:dd98cf00ed9b 280
faheem_chaudhary 5:dd98cf00ed9b 281 @param tokenIndex representing the token in the JSON source
faheem_chaudhary 5:dd98cf00ed9b 282
faheem_chaudhary 5:dd98cf00ed9b 283 @return true if the JSON is valid, false otherwise.
faheem_chaudhary 5:dd98cf00ed9b 284 */
faheem_chaudhary 5:dd98cf00ed9b 285 inline bool isValidToken ( const int tokenIndex ) const;
faheem_chaudhary 5:dd98cf00ed9b 286
faheem_chaudhary 5:dd98cf00ed9b 287
faheem_chaudhary 5:dd98cf00ed9b 288 /** type will return the JSMN type represented by the tokenIndex.
faheem_chaudhary 5:dd98cf00ed9b 289
faheem_chaudhary 5:dd98cf00ed9b 290 @param tokenIndex representing the token in the JSON source. The valid
faheem_chaudhary 5:dd98cf00ed9b 291 value range is 0 to [parsedTokenCount()-1] both inclusive.
faheem_chaudhary 5:dd98cf00ed9b 292
faheem_chaudhary 5:dd98cf00ed9b 293 @return the type represented by tokenIndex. In case of invalid
faheem_chaudhary 5:dd98cf00ed9b 294 tokenIndex, JSMN_UNDEFINED is returned.
faheem_chaudhary 5:dd98cf00ed9b 295 */
mercurywaters 3:fab591fca1e7 296 inline jsmntype_t type ( const int tokenIndex ) const;
faheem_chaudhary 5:dd98cf00ed9b 297
faheem_chaudhary 5:dd98cf00ed9b 298
faheem_chaudhary 5:dd98cf00ed9b 299 /** parent is a utility function to get the parent index of the
faheem_chaudhary 5:dd98cf00ed9b 300 tokenIndex passed.
faheem_chaudhary 5:dd98cf00ed9b 301
faheem_chaudhary 5:dd98cf00ed9b 302 @param tokenIndex representing the token in the JSON source. The valid
faheem_chaudhary 5:dd98cf00ed9b 303 value range is 0 to [parsedTokenCount()-1] both inclusive.
faheem_chaudhary 5:dd98cf00ed9b 304
faheem_chaudhary 5:dd98cf00ed9b 305 @return the parentIndex if the node has a parent, and tokenIndex is a
faheem_chaudhary 5:dd98cf00ed9b 306 valid index. In case of no parent, or invalid tokenIndex, -1
faheem_chaudhary 5:dd98cf00ed9b 307 is returned.
faheem_chaudhary 5:dd98cf00ed9b 308 */
mercurywaters 3:fab591fca1e7 309 inline int parent ( const int tokenIndex ) const;
faheem_chaudhary 5:dd98cf00ed9b 310
faheem_chaudhary 5:dd98cf00ed9b 311
faheem_chaudhary 5:dd98cf00ed9b 312 /** childCount returns the number of children sharing the same parent.
faheem_chaudhary 5:dd98cf00ed9b 313 This utility function is handy for iterating over Arrays or Objects.
faheem_chaudhary 5:dd98cf00ed9b 314
faheem_chaudhary 5:dd98cf00ed9b 315 @param tokenIndex representing the token in the JSON source. The valid
faheem_chaudhary 5:dd98cf00ed9b 316 value range is 0 to [parsedTokenCount()-1] both inclusive.
faheem_chaudhary 5:dd98cf00ed9b 317
faheem_chaudhary 5:dd98cf00ed9b 318 @return non-negative integer representing the number of children
faheem_chaudhary 5:dd98cf00ed9b 319 tokenIndex node has. 0 is a valid number, in case the node has
faheem_chaudhary 5:dd98cf00ed9b 320 no child nodes. -1 will be returned if the tokenIndex is not
faheem_chaudhary 5:dd98cf00ed9b 321 valid.
faheem_chaudhary 5:dd98cf00ed9b 322 */
mercurywaters 3:fab591fca1e7 323 inline int childCount ( const int tokenIndex ) const;
faheem_chaudhary 5:dd98cf00ed9b 324
faheem_chaudhary 5:dd98cf00ed9b 325
faheem_chaudhary 5:dd98cf00ed9b 326 /** tokenLength returns the number of characters a node takes up in JSON
faheem_chaudhary 5:dd98cf00ed9b 327 source string.
faheem_chaudhary 5:dd98cf00ed9b 328
faheem_chaudhary 5:dd98cf00ed9b 329 @param tokenIndex representing the token in the JSON source. The valid
faheem_chaudhary 5:dd98cf00ed9b 330 value range is 0 to [parsedTokenCount()-1] both inclusive.
faheem_chaudhary 5:dd98cf00ed9b 331
faheem_chaudhary 5:dd98cf00ed9b 332 @return positive integer value representing the length of the token
faheem_chaudhary 5:dd98cf00ed9b 333 sub-string in the source JSON. The 0 value is an invalid state
faheem_chaudhary 5:dd98cf00ed9b 334 and should never occur. -1 will be returned in case of invalid
faheem_chaudhary 5:dd98cf00ed9b 335 tokenIndex.
faheem_chaudhary 5:dd98cf00ed9b 336 */
mercurywaters 3:fab591fca1e7 337 inline int tokenLength ( const int tokenIndex ) const;
faheem_chaudhary 5:dd98cf00ed9b 338
faheem_chaudhary 5:dd98cf00ed9b 339
faheem_chaudhary 5:dd98cf00ed9b 340 /** tokenAddress returns the pointer that marks as the start of token
faheem_chaudhary 5:dd98cf00ed9b 341 in JSON source string. This is a utility function for character/string
faheem_chaudhary 5:dd98cf00ed9b 342 manipulation by the caller.
faheem_chaudhary 5:dd98cf00ed9b 343
faheem_chaudhary 5:dd98cf00ed9b 344 @param tokenIndex representing the token in the JSON source. The valid
faheem_chaudhary 5:dd98cf00ed9b 345 value range is 0 to [parsedTokenCount()-1] both inclusive.
faheem_chaudhary 5:dd98cf00ed9b 346
faheem_chaudhary 5:dd98cf00ed9b 347 @return a non-NULL pointer will be returned if tokenIndex is valid, -1
faheem_chaudhary 5:dd98cf00ed9b 348 otherwise.
faheem_chaudhary 5:dd98cf00ed9b 349 */
mercurywaters 3:fab591fca1e7 350 inline const char * tokenAddress ( const int tokenIndex ) const;
mercurywaters 3:fab591fca1e7 351
faheem_chaudhary 5:dd98cf00ed9b 352
faheem_chaudhary 5:dd98cf00ed9b 353 /** tokenInterValue will convert the value as int represented by the
faheem_chaudhary 5:dd98cf00ed9b 354 tokenIndex. A typical use is that caller has found the Key-index, and
faheem_chaudhary 5:dd98cf00ed9b 355 then has retrieved the Value-index (by using findChildIndexOf function)
faheem_chaudhary 5:dd98cf00ed9b 356 , and now they want to read the value of Value-index, as integer value.
faheem_chaudhary 5:dd98cf00ed9b 357
faheem_chaudhary 5:dd98cf00ed9b 358 @param tokenIndex representing the "value" in the JSON source. The
faheem_chaudhary 5:dd98cf00ed9b 359 valid value range is 0 to [parsedTokenCount()-1] both inclusive.
faheem_chaudhary 5:dd98cf00ed9b 360
faheem_chaudhary 5:dd98cf00ed9b 361 @param returnValue is a return-parameter passed by reference to hold up
faheem_chaudhary 5:dd98cf00ed9b 362 the integer value parsed by this function. If the converted
faheem_chaudhary 5:dd98cf00ed9b 363 value would be out of the range of representable values by an
faheem_chaudhary 5:dd98cf00ed9b 364 int, it causes undefined behavior. It is caller's
faheem_chaudhary 5:dd98cf00ed9b 365 responsibility to check for these cases.
faheem_chaudhary 5:dd98cf00ed9b 366
faheem_chaudhary 5:dd98cf00ed9b 367 @return 0 if the operation is successful. -1 if tokenIndex is invalid.
faheem_chaudhary 5:dd98cf00ed9b 368 */
faheem_chaudhary 5:dd98cf00ed9b 369 int tokenIntegerValue ( const int tokenIndex, int &returnValue ) const;
faheem_chaudhary 5:dd98cf00ed9b 370
faheem_chaudhary 5:dd98cf00ed9b 371
faheem_chaudhary 5:dd98cf00ed9b 372 /** tokenNumberValue will convert the value as float represented by the
faheem_chaudhary 5:dd98cf00ed9b 373 tokenIndex. A typical use is that caller has found the Key-index, and
faheem_chaudhary 5:dd98cf00ed9b 374 then has retrieved the Value-index (by using findChildIndexOf function)
faheem_chaudhary 5:dd98cf00ed9b 375 , and now they want to read the value of Value-index, as floating-point
faheem_chaudhary 5:dd98cf00ed9b 376 value.
faheem_chaudhary 5:dd98cf00ed9b 377
faheem_chaudhary 5:dd98cf00ed9b 378 @param tokenIndex representing the "value" in the JSON source. The
faheem_chaudhary 5:dd98cf00ed9b 379 valid value range is 0 to [parsedTokenCount()-1] both inclusive.
faheem_chaudhary 5:dd98cf00ed9b 380
faheem_chaudhary 5:dd98cf00ed9b 381 @param returnValue is a return-parameter passed by reference to hold up
faheem_chaudhary 5:dd98cf00ed9b 382 the floating-point value parsed by this function. If the
faheem_chaudhary 5:dd98cf00ed9b 383 converted value would be out of the range of representable
faheem_chaudhary 5:dd98cf00ed9b 384 values by a float, it causes undefined behavior. It is caller's
faheem_chaudhary 5:dd98cf00ed9b 385 responsibility to check for these cases.
mercurywaters 3:fab591fca1e7 386
faheem_chaudhary 5:dd98cf00ed9b 387 @return 0 if the operation is successful. -1 if tokenIndex is invalid.
faheem_chaudhary 5:dd98cf00ed9b 388 */
faheem_chaudhary 5:dd98cf00ed9b 389 int tokenNumberValue ( const int tokenIndex, float &returnValue ) const;
faheem_chaudhary 5:dd98cf00ed9b 390
faheem_chaudhary 5:dd98cf00ed9b 391
faheem_chaudhary 5:dd98cf00ed9b 392 /** tokenBooleanValue will convert the value as bool represented by
faheem_chaudhary 5:dd98cf00ed9b 393 the tokenIndex. A typical use is that caller has found the Key-index,
faheem_chaudhary 5:dd98cf00ed9b 394 and then has retrieved the Value-index (by using findChildIndexOf
faheem_chaudhary 5:dd98cf00ed9b 395 function), and now they want to read the value of Value-index, as
faheem_chaudhary 5:dd98cf00ed9b 396 boolean value.
faheem_chaudhary 5:dd98cf00ed9b 397
faheem_chaudhary 5:dd98cf00ed9b 398 @param tokenIndex representing the "value" in the JSON source. The
faheem_chaudhary 5:dd98cf00ed9b 399 valid value range is 0 to [parsedTokenCount()-1] both inclusive.
faheem_chaudhary 5:dd98cf00ed9b 400
faheem_chaudhary 5:dd98cf00ed9b 401 @param returnValue is a return-parameter passed by reference to hold up
faheem_chaudhary 5:dd98cf00ed9b 402 the bool value parsed by this function.
mercurywaters 3:fab591fca1e7 403
faheem_chaudhary 5:dd98cf00ed9b 404 @return 0 if the operation is successful. -1 if tokenIndex is invalid.
faheem_chaudhary 5:dd98cf00ed9b 405 */
faheem_chaudhary 5:dd98cf00ed9b 406 int tokenBooleanValue ( const int tokenIndex, bool &returnValue ) const;
faheem_chaudhary 5:dd98cf00ed9b 407
faheem_chaudhary 5:dd98cf00ed9b 408
faheem_chaudhary 5:dd98cf00ed9b 409 /** unescape is a utility function to unescape a JSON string. This
faheem_chaudhary 5:dd98cf00ed9b 410 function does not change any state of Json object, and is a pure
faheem_chaudhary 5:dd98cf00ed9b 411 static utility function. This function is in-pace unescaping, and WILL
faheem_chaudhary 5:dd98cf00ed9b 412 modify the source parameter.
faheem_chaudhary 5:dd98cf00ed9b 413
faheem_chaudhary 5:dd98cf00ed9b 414 @param jsonString representing an escaped JSON string. This parameter
faheem_chaudhary 5:dd98cf00ed9b 415 is also the return parameter as well. All modifications will be
faheem_chaudhary 5:dd98cf00ed9b 416 reflected in this parameter.
faheem_chaudhary 5:dd98cf00ed9b 417
faheem_chaudhary 5:dd98cf00ed9b 418 @return pointer to unescaped JSON string. This is exactly the same
faheem_chaudhary 5:dd98cf00ed9b 419 pointer as jsonString parameter.
faheem_chaudhary 5:dd98cf00ed9b 420 */
faheem_chaudhary 4:ae34010d87e5 421 static char * unescape ( char * jsonString );
mercurywaters 3:fab591fca1e7 422 };
mercurywaters 3:fab591fca1e7 423
faheem_chaudhary 5:dd98cf00ed9b 424 inline int Json::parsedTokenCount () const
faheem_chaudhary 5:dd98cf00ed9b 425 {
faheem_chaudhary 5:dd98cf00ed9b 426 return tokenCount;
faheem_chaudhary 5:dd98cf00ed9b 427 }
faheem_chaudhary 5:dd98cf00ed9b 428
mercurywaters 3:fab591fca1e7 429 inline bool Json::isValidJson () const
mercurywaters 3:fab591fca1e7 430 {
mercurywaters 3:fab591fca1e7 431 return ( tokenCount >= 1 );
mercurywaters 3:fab591fca1e7 432 }
mercurywaters 3:fab591fca1e7 433
faheem_chaudhary 5:dd98cf00ed9b 434 inline bool Json::isValidToken ( const int tokenIndex ) const
faheem_chaudhary 5:dd98cf00ed9b 435 {
faheem_chaudhary 5:dd98cf00ed9b 436 return ( tokenIndex >= 0 && tokenIndex < tokenCount );
faheem_chaudhary 5:dd98cf00ed9b 437 }
faheem_chaudhary 5:dd98cf00ed9b 438
mercurywaters 3:fab591fca1e7 439 inline jsmntype_t Json::type ( const int tokenIndex ) const
mercurywaters 3:fab591fca1e7 440 {
faheem_chaudhary 5:dd98cf00ed9b 441 jsmntype_t retVal = JSMN_UNDEFINED;
faheem_chaudhary 5:dd98cf00ed9b 442
faheem_chaudhary 5:dd98cf00ed9b 443 if ( isValidToken ( tokenIndex ) )
faheem_chaudhary 5:dd98cf00ed9b 444 {
faheem_chaudhary 5:dd98cf00ed9b 445 retVal = tokens [ tokenIndex ].type;
faheem_chaudhary 5:dd98cf00ed9b 446 }
faheem_chaudhary 5:dd98cf00ed9b 447
faheem_chaudhary 5:dd98cf00ed9b 448 return retVal;
mercurywaters 3:fab591fca1e7 449 }
mercurywaters 3:fab591fca1e7 450
mercurywaters 3:fab591fca1e7 451 inline int Json::parent ( const int tokenIndex ) const
mercurywaters 3:fab591fca1e7 452 {
faheem_chaudhary 5:dd98cf00ed9b 453 int retVal = -1;
faheem_chaudhary 5:dd98cf00ed9b 454
faheem_chaudhary 5:dd98cf00ed9b 455 if ( isValidToken ( tokenIndex ) )
faheem_chaudhary 5:dd98cf00ed9b 456 {
faheem_chaudhary 5:dd98cf00ed9b 457 retVal = tokens [ tokenIndex ].parent;
faheem_chaudhary 5:dd98cf00ed9b 458 }
faheem_chaudhary 5:dd98cf00ed9b 459
faheem_chaudhary 5:dd98cf00ed9b 460 return retVal;
mercurywaters 3:fab591fca1e7 461 }
mercurywaters 3:fab591fca1e7 462
mercurywaters 3:fab591fca1e7 463 inline int Json::childCount ( const int tokenIndex ) const
mercurywaters 3:fab591fca1e7 464 {
faheem_chaudhary 5:dd98cf00ed9b 465 int retVal = -1;
faheem_chaudhary 5:dd98cf00ed9b 466
faheem_chaudhary 5:dd98cf00ed9b 467 if ( isValidToken ( tokenIndex ) )
faheem_chaudhary 5:dd98cf00ed9b 468 {
faheem_chaudhary 5:dd98cf00ed9b 469 retVal = tokens [ tokenIndex ].childCount;
faheem_chaudhary 5:dd98cf00ed9b 470 }
faheem_chaudhary 5:dd98cf00ed9b 471
faheem_chaudhary 5:dd98cf00ed9b 472 return retVal;
mercurywaters 3:fab591fca1e7 473 }
mercurywaters 3:fab591fca1e7 474
mercurywaters 3:fab591fca1e7 475 inline int Json::tokenLength ( const int tokenIndex ) const
mercurywaters 3:fab591fca1e7 476 {
faheem_chaudhary 5:dd98cf00ed9b 477 int retVal = -1;
faheem_chaudhary 5:dd98cf00ed9b 478
faheem_chaudhary 5:dd98cf00ed9b 479 if ( isValidToken ( tokenIndex ) )
faheem_chaudhary 5:dd98cf00ed9b 480 {
faheem_chaudhary 5:dd98cf00ed9b 481 retVal = tokens [ tokenIndex ].end - tokens [ tokenIndex ].start;
faheem_chaudhary 5:dd98cf00ed9b 482 }
faheem_chaudhary 5:dd98cf00ed9b 483
faheem_chaudhary 5:dd98cf00ed9b 484 return retVal;
mercurywaters 3:fab591fca1e7 485 }
mercurywaters 3:fab591fca1e7 486
mercurywaters 3:fab591fca1e7 487 inline const char * Json::tokenAddress ( const int tokenIndex ) const
mercurywaters 3:fab591fca1e7 488 {
faheem_chaudhary 5:dd98cf00ed9b 489 char * retVal = NULL;
mercurywaters 3:fab591fca1e7 490
faheem_chaudhary 5:dd98cf00ed9b 491 if ( isValidToken ( tokenIndex ) )
faheem_chaudhary 4:ae34010d87e5 492 {
faheem_chaudhary 5:dd98cf00ed9b 493 retVal = (char *) source + tokens [ tokenIndex ].start;
faheem_chaudhary 4:ae34010d87e5 494 }
faheem_chaudhary 5:dd98cf00ed9b 495
faheem_chaudhary 5:dd98cf00ed9b 496 return retVal;
faheem_chaudhary 4:ae34010d87e5 497 }
faheem_chaudhary 4:ae34010d87e5 498
mercurywaters 3:fab591fca1e7 499 #endif
mercurywaters 3:fab591fca1e7 500