1 | /*
|
---|
2 | SuperEasyJSON
|
---|
3 | http://www.sourceforge.net/p/supereasyjson
|
---|
4 |
|
---|
5 | The MIT License (MIT)
|
---|
6 |
|
---|
7 | Copyright (c) 2013 Jeff Weinstein (jeff.weinstein at gmail)
|
---|
8 |
|
---|
9 | Permission is hereby granted, free of charge, to any person obtaining a copy
|
---|
10 | of this software and associated documentation files (the "Software"), to deal
|
---|
11 | in the Software without restriction, including without limitation the rights
|
---|
12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
---|
13 | copies of the Software, and to permit persons to whom the Software is
|
---|
14 | furnished to do so, subject to the following conditions:
|
---|
15 |
|
---|
16 | The above copyright notice and this permission notice shall be included in
|
---|
17 | all copies or substantial portions of the Software.
|
---|
18 |
|
---|
19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
---|
20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
---|
21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
---|
22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
---|
23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
---|
24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
---|
25 | THE SOFTWARE.
|
---|
26 |
|
---|
27 | CHANGELOG:
|
---|
28 | ==========
|
---|
29 |
|
---|
30 | 8/31/2014:
|
---|
31 | ---------
|
---|
32 | * Fixed bug from last update that broke false/true boolean usage. Courtesy of Vasi B.
|
---|
33 | * Change postfix increment of iterators in Serialize to prefix, courtesy of Vasi B.
|
---|
34 | * More improvements to validity checking of non string/object/array types. Should
|
---|
35 | catch even more invalid usage types such as -1jE5, falsee, trueeeeeee
|
---|
36 | {"key" : potato} (that should be {"key" : "potato"}), etc.
|
---|
37 | * Switched to strtol and strtod from atof/atoi in Serialize for better error handling.
|
---|
38 | * Fix for GCC order of initialization warnings, courtsey of Vasi B.
|
---|
39 |
|
---|
40 | 8/17/2014:
|
---|
41 | ----------
|
---|
42 | * Better error handling (and bug fixing) for invalid JSON. Previously, something such as:
|
---|
43 | {"def": j[{"a": 100}],"abc": 123}
|
---|
44 | would result in at best, a crash, and at worst, nothing when this was passed to
|
---|
45 | the Deserialize method. Note that the "j" is invalid in this example. This led
|
---|
46 | to further fixes for other invalid syntax:
|
---|
47 | - Use of multiple 'e', for example: 1ee4 is not valid
|
---|
48 | - Use of '.' when not preceded by a digit is invalid. For example: .1 is
|
---|
49 | incorrect, but 0.1 is fine.
|
---|
50 | - Using 'e' when not preceded by a digit. For example, e4 isn't valid but 1e4 is.
|
---|
51 |
|
---|
52 | The deserialize method should properly handle these problems and when there's an
|
---|
53 | error, it returns a Value object with the NULLVal type. Check this type to see
|
---|
54 | if there's an error.
|
---|
55 |
|
---|
56 | Issue reported by Imre Pechan.
|
---|
57 |
|
---|
58 | 7/21/2014:
|
---|
59 | ----------
|
---|
60 | * All asserts removed and replaced with exceptions, as per request from many users.
|
---|
61 | Instead of asserting, functions will throw a std::runtime_error with
|
---|
62 | appropriate error message.
|
---|
63 | * Added versions of the Value::To* functions that take a default parameter.
|
---|
64 | In the event of an error (like calling Value::ToInt() when it's type is an Object),
|
---|
65 | the default value you specified will be returned. Courtesy of PeterSvP
|
---|
66 | * Fixed type mismatch warning, courtesy of Per Rovegård
|
---|
67 | * Initialized some variables in the various Value constructors to defaults for
|
---|
68 | better support with full blast g++ warnings, courtesy of Mark Odell.
|
---|
69 | * Changed Value::ToString to return a const std::string& instead of std::string
|
---|
70 | to avoid unnecessary copying.
|
---|
71 | * Improved some commenting
|
---|
72 | * Fixed a bug where a capital E for scientific notation numbers wasn't
|
---|
73 | recognized, only lowercase e.
|
---|
74 | * VASTLY OVERHAULED AND IMPROVED THE README FILE, PLEASE CONSULT IT FOR
|
---|
75 | IN DEPTH USAGE AND EXAMPLES.
|
---|
76 |
|
---|
77 |
|
---|
78 | 2/8/2014:
|
---|
79 | ---------
|
---|
80 | MAJOR BUG FIXES, all courtesy of Per Rovegård, Ph.D.
|
---|
81 | * Feature request: HasKey and HasKeys added to Value for convenience and
|
---|
82 | to avoid having to make a temporary object.
|
---|
83 | * Strings should now be properly unescaped. Previously, as an example, the
|
---|
84 | string "\/Date(1390431949211+0100)\/\" would be parsed as
|
---|
85 | \/Date(1390431949211+0100)\/. The string is now properly parsed as
|
---|
86 | /Date(1390431949211+0100)/.
|
---|
87 | As per http://www.json.org the other escape characters including
|
---|
88 | \u+4 hex digits will now be properly unescaped. So for example,
|
---|
89 | \u0061 now becomes "A".
|
---|
90 | * Serialize now supports serializing a toplevel array (which is valid JSON).
|
---|
91 | The parameter it takes is now a Value, but existing code doesn't
|
---|
92 | need to be changed.
|
---|
93 | * Fixed bug with checking for proper opening/closing sequence for braces/brackets.
|
---|
94 | Previously, this code:
|
---|
95 | const char *json = "{\"arr\":[{}}]}";
|
---|
96 | auto val = json::Deserialize(json);
|
---|
97 | worked fine with no errors. That's a bug. I did a major overhaul so that
|
---|
98 | now improperly formatted pairs will now correctly result in an error.
|
---|
99 | * Made internal deserialize methods static
|
---|
100 |
|
---|
101 | 1/30/2014:
|
---|
102 | ----------
|
---|
103 | * Changed #pragma once to the standard #ifndef header guard style for
|
---|
104 | better compatibility.
|
---|
105 | * Added a [] operator for Value that takes a const char* as an argument
|
---|
106 | to avoid having to explicitly (and annoyingly) cast to std::string.
|
---|
107 | Thus, my_value["asdf"] = "a string" should now work fine.
|
---|
108 | The same has been added to the Object class.
|
---|
109 | * Added non-operator methods of casting a Value to int/string/bool/etc.
|
---|
110 | Implicitly casting a Value to a std::string doesn't work as per C++
|
---|
111 | rules. As such, previously to assign a Value to a std::string you
|
---|
112 | had to do:
|
---|
113 | my_std_string = (std::string)my_value;
|
---|
114 | You can now instead do:
|
---|
115 | my_std_string = my_value.ToString();
|
---|
116 | If you want more information on why this can't be done, please read
|
---|
117 | this topic for more details:
|
---|
118 | http://stackoverflow.com/questions/3518145/c-overloading-conversion-operator-for-custom-type-to-stdstring
|
---|
119 |
|
---|
120 | 1/27/2014
|
---|
121 | ----------
|
---|
122 | * Deserialize will now return a NULLVal Value instance if there was an
|
---|
123 | error instead of asserting. This way you can handle however you want to
|
---|
124 | invalid JSON being passed in. As a top level object must be either an
|
---|
125 | array or an object, a NULL value return indicates an invalid result.
|
---|
126 |
|
---|
127 | 1/11/2014
|
---|
128 | ---------
|
---|
129 | * Major bug fix: Strings containing []{} characters could cause
|
---|
130 | parsing errors under certain conditions. I've just tested
|
---|
131 | the class parsing a 300KB JSON file with all manner of bizarre
|
---|
132 | characters and permutations and it worked, so hopefully this should
|
---|
133 | be the end of "major bug" fixes.
|
---|
134 |
|
---|
135 | 1/10/2014
|
---|
136 | ---------
|
---|
137 | Bug fixes courtesy of Gerry Beauregard:
|
---|
138 | * Pretty big bug: was using wrong string paramter in ::Deserialize
|
---|
139 | and furthermore it wasn't being trimmed.
|
---|
140 | * Object::HasKeys now casts the return value to avoid compiler warnings.
|
---|
141 | * Slight optimization to the Trim function
|
---|
142 | * Made asserts in ::Deserialize easier to read
|
---|
143 |
|
---|
144 | 1/9/2014
|
---|
145 | --------
|
---|
146 | * Major bug fix: for JSON strings containing \" (as in, two characters,
|
---|
147 | not the escaped " character), the lib would mess up and not parse
|
---|
148 | correctly.
|
---|
149 | * Major bug fix: I erroneously was assuming that all root JSON types
|
---|
150 | had to be an object. This was an oversight, as a root JSON
|
---|
151 | object can be an array. I have therefore changed the Deserialize
|
---|
152 | method to return a json::Value rather than a json::Object. This
|
---|
153 | will NOT impact any existing code you have, as a json::Value will
|
---|
154 | cast to a json::Object (if it is indeed an object). But for
|
---|
155 | correctness, you should be using json::Value = Deserialize...
|
---|
156 | The Value type can be checked if it's an array (or any other type),
|
---|
157 | and furthermore can even be accessed with the [] operator for
|
---|
158 | convenience.
|
---|
159 | * I've made the NULL value type set numeric fields to 0 and bool to false.
|
---|
160 | This is for convenience for using the NULL type as a default return
|
---|
161 | value in your code.
|
---|
162 | * asserts added to casting (Gerry Beauregard)
|
---|
163 | * Added method HasKeys to json::Object which will check if all the keys
|
---|
164 | specified are in the object, returning the index of the first key
|
---|
165 | not found or -1 if all found (hoppe).
|
---|
166 |
|
---|
167 | 1/4/2014
|
---|
168 | --------
|
---|
169 | * Fixed bug where booleans were being parsed as doubles (Gerry Beauregard).
|
---|
170 |
|
---|
171 | 1/2/2014 v3
|
---|
172 | ------------
|
---|
173 | * More missing headers added for VisualStudio 2012
|
---|
174 | * Switched to snprintf instead of sprintf (or sprintf_s in MSVC)
|
---|
175 |
|
---|
176 | 1/2/2014 v2
|
---|
177 | -----------
|
---|
178 | * Added yet more missing headers for compiling on GNU and Linux systems
|
---|
179 | * Made Deserialize copy the passed in string so it won't mangle it
|
---|
180 |
|
---|
181 | 1/2/2014
|
---|
182 | --------
|
---|
183 | * Fixed previous changelog years. Got ahead of myself and marked them
|
---|
184 | as 2014 when they were in fact done in 2013.
|
---|
185 | * Added const version of [] to Array/Object/Value
|
---|
186 | * Removed C++11 requirements, should work with older compilers
|
---|
187 | (thanks to Meng Wang for pointing that out)
|
---|
188 | * Made ValueMap and ValueVector typedefs in Object/Value public
|
---|
189 | so you can actually iterate over the class
|
---|
190 | * Added HasKey and HasValue to Object/Array for convenience
|
---|
191 | (note this could have been done comparing .find to .end)
|
---|
192 |
|
---|
193 | 12/29/2013 v2
|
---|
194 | -------------
|
---|
195 | * Added .size() field to Value. Returns 1 for non Array/Object types,
|
---|
196 | otherwise the number of elements contained.
|
---|
197 | * Added .find() to Object to search for a key. Returns Object::end()
|
---|
198 | if not found, otherwise the Value.
|
---|
199 | Example: bool found = my_obj.find("some key") != my_obj.end();
|
---|
200 | * Added .find() to Array to search for a value. Just a convenience
|
---|
201 | wrapper for std::find(Array::begin(), Array::end(), Value)
|
---|
202 | * Added ==, !=, <, >, <=, >= operators to Object/Array/Value.
|
---|
203 | For Objects/Arrays, the operators function just like they do for a
|
---|
204 | std::map and std::vector, respectively.
|
---|
205 | * Added IsNumeric to Value to indicate if it's an int/float/double type.
|
---|
206 |
|
---|
207 | 12/29/2013
|
---|
208 | ----------
|
---|
209 | * Added the DoubleVal type which stores, you guessed it, double values.
|
---|
210 | * Bug fix for floats with an exact integer value. Now, setting any numerical
|
---|
211 | field will also set the fields for the other numerical types. So if you
|
---|
212 | have obj["value"] = 12, then the int/float/double cast methods will
|
---|
213 | return 12/12.0f/12.0. Previously, in the example above, only the int
|
---|
214 | value was set, making a cast to float return 0.
|
---|
215 | * Bug fix for deserializing JSON strings that contained large integer values.
|
---|
216 | Now if the numerical value of a key in a JSON string contains a number
|
---|
217 | less than INT_MIN or greater than INT_MAX it will be stored as a double.
|
---|
218 | Note that as mentioned above, all numerical fields are set.
|
---|
219 | * Should work fine with scientific notation values now.
|
---|
220 |
|
---|
221 | 12/28/2013
|
---|
222 | ----------
|
---|
223 |
|
---|
224 | * Fixed a bug where if there were spaces around values or key names in a JSON
|
---|
225 | string passed in to Deserialize, invalid results or asserts would occur.
|
---|
226 | (Fix courtesy of Gerry Beauregard)
|
---|
227 |
|
---|
228 | * Added method named "Clear()" to Object/Array/Value to reset state
|
---|
229 |
|
---|
230 | * Added license to header file for easyness (totally valid word).
|
---|
231 | */
|
---|
232 |
|
---|
233 | #ifndef __SUPER_EASY_JSON_H__
|
---|
234 | #define __SUPER_EASY_JSON_H__
|
---|
235 |
|
---|
236 | #include <vector>
|
---|
237 | #include <map>
|
---|
238 | #include <string>
|
---|
239 | #include <stdexcept>
|
---|
240 |
|
---|
241 |
|
---|
242 | // PLEASE SEE THE README FOR USAGE INFORMATION AND EXAMPLES. Comments will be kept to a minimum to reduce clutter.
|
---|
243 | namespace json
|
---|
244 | {
|
---|
245 | enum ValueType
|
---|
246 | {
|
---|
247 | NULLVal,
|
---|
248 | StringVal,
|
---|
249 | IntVal,
|
---|
250 | FloatVal,
|
---|
251 | DoubleVal,
|
---|
252 | ObjectVal,
|
---|
253 | ArrayVal,
|
---|
254 | BoolVal
|
---|
255 | };
|
---|
256 |
|
---|
257 | class Value;
|
---|
258 |
|
---|
259 | // Represents a JSON object which is of the form {string:value, string:value, ...} Where string is the "key" name and is
|
---|
260 | // of the form "" or "characters". Value is either of: string, number, object, array, boolean, null
|
---|
261 | class Object
|
---|
262 | {
|
---|
263 | public:
|
---|
264 |
|
---|
265 | // This is the type used to store key/value pairs. If you want to get an iterator for this class to iterate over its members,
|
---|
266 | // use this.
|
---|
267 | // For example: Object::ValueMap::iterator my_iterator;
|
---|
268 | typedef std::map<std::string, Value> ValueMap;
|
---|
269 |
|
---|
270 | protected:
|
---|
271 |
|
---|
272 | ValueMap mValues;
|
---|
273 |
|
---|
274 | public:
|
---|
275 |
|
---|
276 | Object();
|
---|
277 | Object(const Object& obj);
|
---|
278 |
|
---|
279 | Object& operator =(const Object& obj);
|
---|
280 |
|
---|
281 | friend bool operator ==(const Object& lhs, const Object& rhs);
|
---|
282 | inline friend bool operator !=(const Object& lhs, const Object& rhs) {return !(lhs == rhs);}
|
---|
283 | friend bool operator <(const Object& lhs, const Object& rhs);
|
---|
284 | inline friend bool operator >(const Object& lhs, const Object& rhs) {return operator<(rhs, lhs);}
|
---|
285 | inline friend bool operator <=(const Object& lhs, const Object& rhs) {return !operator>(lhs, rhs);}
|
---|
286 | inline friend bool operator >=(const Object& lhs, const Object& rhs) {return !operator<(lhs, rhs);}
|
---|
287 |
|
---|
288 | // Just like a std::map, you can get the value for a key by using the index operator. You could also
|
---|
289 | // use this to insert a value if it doesn't exist, or overwrite it if it does. Example:
|
---|
290 | // Value my_val = my_object["some key name"];
|
---|
291 | // my_object["some key name"] = "overwriting the value with this new string value";
|
---|
292 | // my_object["new key name"] = "a new key being inserted";
|
---|
293 | Value& operator [](const std::string& key);
|
---|
294 | const Value& operator [](const std::string& key) const;
|
---|
295 | Value& operator [](const char* key);
|
---|
296 | const Value& operator [](const char* key) const;
|
---|
297 |
|
---|
298 | ValueMap::const_iterator begin() const;
|
---|
299 | ValueMap::const_iterator end() const;
|
---|
300 | ValueMap::iterator begin();
|
---|
301 | ValueMap::iterator end();
|
---|
302 |
|
---|
303 | // Find will return end() if the key can't be found, just like std::map does. ->first will be the key (a std::string),
|
---|
304 | // ->second will be the Value.
|
---|
305 | ValueMap::iterator find(const std::string& key);
|
---|
306 | ValueMap::const_iterator find(const std::string& key) const;
|
---|
307 |
|
---|
308 | // Convenience wrapper to search for a key
|
---|
309 | bool HasKey(const std::string& key) const;
|
---|
310 |
|
---|
311 | // Checks if the object contains all the keys in the array. If it does, returns -1.
|
---|
312 | // If it doesn't, returns the index of the first key it couldn't find.
|
---|
313 | int HasKeys(const std::vector<std::string>& keys) const;
|
---|
314 | int HasKeys(const char* keys[], int key_count) const;
|
---|
315 |
|
---|
316 | // Removes all values and resets the state back to default
|
---|
317 | void Clear();
|
---|
318 |
|
---|
319 | size_t size() const {return mValues.size();}
|
---|
320 |
|
---|
321 | };
|
---|
322 |
|
---|
323 | // Represents a JSON Array which is of the form [value, value, ...] where value is either of: string, number, object, array, boolean, null
|
---|
324 | class Array
|
---|
325 | {
|
---|
326 | public:
|
---|
327 |
|
---|
328 | // This is the type used to store values. If you want to get an iterator for this class to iterate over its members,
|
---|
329 | // use this.
|
---|
330 | // For example: Array::ValueVector::iterator my_array_iterator;
|
---|
331 | typedef std::vector<Value> ValueVector;
|
---|
332 |
|
---|
333 | protected:
|
---|
334 |
|
---|
335 | ValueVector mValues;
|
---|
336 |
|
---|
337 | public:
|
---|
338 |
|
---|
339 | Array();
|
---|
340 | Array(const Array& a);
|
---|
341 |
|
---|
342 | Array& operator =(const Array& a);
|
---|
343 |
|
---|
344 | friend bool operator ==(const Array& lhs, const Array& rhs);
|
---|
345 | inline friend bool operator !=(const Array& lhs, const Array& rhs) {return !(lhs == rhs);}
|
---|
346 | friend bool operator <(const Array& lhs, const Array& rhs);
|
---|
347 | inline friend bool operator >(const Array& lhs, const Array& rhs) {return operator<(rhs, lhs);}
|
---|
348 | inline friend bool operator <=(const Array& lhs, const Array& rhs) {return !operator>(lhs, rhs);}
|
---|
349 | inline friend bool operator >=(const Array& lhs, const Array& rhs) {return !operator<(lhs, rhs);}
|
---|
350 |
|
---|
351 | Value& operator[] (size_t i);
|
---|
352 | const Value& operator[] (size_t i) const;
|
---|
353 |
|
---|
354 | ValueVector::const_iterator begin() const;
|
---|
355 | ValueVector::const_iterator end() const;
|
---|
356 | ValueVector::iterator begin();
|
---|
357 | ValueVector::iterator end();
|
---|
358 |
|
---|
359 | // Just a convenience wrapper for doing a std::find(Array::begin(), Array::end(), Value)
|
---|
360 | ValueVector::iterator find(const Value& v);
|
---|
361 | ValueVector::const_iterator find(const Value& v) const;
|
---|
362 |
|
---|
363 | // Convenience wrapper to check if a value is in the array
|
---|
364 | bool HasValue(const Value& v) const;
|
---|
365 |
|
---|
366 | // Removes all values and resets the state back to default
|
---|
367 | void Clear();
|
---|
368 |
|
---|
369 | void push_back(const Value& v);
|
---|
370 | void insert(size_t index, const Value& v);
|
---|
371 | size_t size() const;
|
---|
372 | };
|
---|
373 |
|
---|
374 | // Represents a JSON value which is either of: string, number, object, array, boolean, null
|
---|
375 | class Value
|
---|
376 | {
|
---|
377 | protected:
|
---|
378 |
|
---|
379 | ValueType mValueType;
|
---|
380 | int mIntVal;
|
---|
381 | float mFloatVal;
|
---|
382 | double mDoubleVal;
|
---|
383 | std::string mStringVal;
|
---|
384 | Object mObjectVal;
|
---|
385 | Array mArrayVal;
|
---|
386 | bool mBoolVal;
|
---|
387 |
|
---|
388 | public:
|
---|
389 |
|
---|
390 | Value() : mValueType(NULLVal), mIntVal(0), mFloatVal(0), mDoubleVal(0), mBoolVal(false) {}
|
---|
391 | Value(int v) : mValueType(IntVal), mIntVal(v), mFloatVal((float)v), mDoubleVal((double)v), mBoolVal(false) {}
|
---|
392 | Value(float v) : mValueType(FloatVal), mIntVal((int)v), mFloatVal(v), mDoubleVal((double)v), mBoolVal(false) {}
|
---|
393 | Value(double v) : mValueType(DoubleVal), mIntVal((int)v), mFloatVal((float)v), mDoubleVal(v), mBoolVal(false) {}
|
---|
394 | Value(const std::string& v) : mValueType(StringVal), mIntVal(), mFloatVal(), mDoubleVal(), mStringVal(v), mBoolVal(false) {}
|
---|
395 | Value(const char* v) : mValueType(StringVal), mIntVal(), mFloatVal(), mDoubleVal(), mStringVal(v), mBoolVal(false) {}
|
---|
396 | Value(const Object& v) : mValueType(ObjectVal), mIntVal(), mFloatVal(), mDoubleVal(), mObjectVal(v), mBoolVal(false) {}
|
---|
397 | Value(const Array& v) : mValueType(ArrayVal), mIntVal(), mFloatVal(), mDoubleVal(), mArrayVal(v), mBoolVal(false) {}
|
---|
398 | Value(bool v) : mValueType(BoolVal), mIntVal(), mFloatVal(), mDoubleVal(), mBoolVal(v) {}
|
---|
399 | Value(const Value& v);
|
---|
400 |
|
---|
401 | // Use this to determine the underlying type that this Value class represents. It will be one of the
|
---|
402 | // ValueType enums as defined at the top of this file.
|
---|
403 | ValueType GetType() const {return mValueType;}
|
---|
404 |
|
---|
405 | // Convenience method that checks if this type is an int/double/float
|
---|
406 | bool IsNumeric() const {return (mValueType == IntVal) || (mValueType == DoubleVal) || (mValueType == FloatVal);}
|
---|
407 |
|
---|
408 | Value& operator =(const Value& v);
|
---|
409 |
|
---|
410 | friend bool operator ==(const Value& lhs, const Value& rhs);
|
---|
411 | inline friend bool operator !=(const Value& lhs, const Value& rhs) {return !(lhs == rhs);}
|
---|
412 | friend bool operator <(const Value& lhs, const Value& rhs);
|
---|
413 | inline friend bool operator >(const Value& lhs, const Value& rhs) {return operator<(rhs, lhs);}
|
---|
414 | inline friend bool operator <=(const Value& lhs, const Value& rhs) {return !operator>(lhs, rhs);}
|
---|
415 | inline friend bool operator >=(const Value& lhs, const Value& rhs) {return !operator<(lhs, rhs);}
|
---|
416 |
|
---|
417 |
|
---|
418 | // If this value represents an object or array, you can use the [] indexing operator
|
---|
419 | // just like you would with the native json::Array or json::Object classes.
|
---|
420 | // THROWS A std::runtime_error IF NOT AN ARRAY OR OBJECT.
|
---|
421 | Value& operator [](size_t idx);
|
---|
422 | const Value& operator [](size_t idx) const;
|
---|
423 | Value& operator [](const std::string& key);
|
---|
424 | const Value& operator [](const std::string& key) const;
|
---|
425 | Value& operator [](const char* key);
|
---|
426 | const Value& operator [](const char* key) const;
|
---|
427 |
|
---|
428 | // If this value represents an object, these methods let you check if a single key or an array of
|
---|
429 | // keys is contained within it.
|
---|
430 | // THROWS A std::runtime_error IF NOT AN OBJECT.
|
---|
431 | bool HasKey(const std::string& key) const;
|
---|
432 | int HasKeys(const std::vector<std::string>& keys) const;
|
---|
433 | int HasKeys(const char* keys[], int key_count) const;
|
---|
434 |
|
---|
435 |
|
---|
436 | // non-operator versions, **will throw a std::runtime_error if invalid with an appropriate error message**
|
---|
437 | int ToInt() const;
|
---|
438 | float ToFloat() const;
|
---|
439 | double ToDouble() const;
|
---|
440 | bool ToBool() const;
|
---|
441 | const std::string& ToString() const;
|
---|
442 | Object ToObject() const;
|
---|
443 | Array ToArray() const;
|
---|
444 |
|
---|
445 | // These versions do the same as above but will return your specified default value in the event there's an error, and thus **don't** throw an exception.
|
---|
446 | int ToInt(int def) const {return IsNumeric() ? mIntVal : def;}
|
---|
447 | float ToFloat(float def) const {return IsNumeric() ? mFloatVal : def;}
|
---|
448 | double ToDouble(double def) const {return IsNumeric() ? mDoubleVal : def;}
|
---|
449 | bool ToBool(bool def) const {return (mValueType == BoolVal) ? mBoolVal : def;}
|
---|
450 | const std::string& ToString(const std::string& def) const {return (mValueType == StringVal) ? mStringVal : def;}
|
---|
451 |
|
---|
452 |
|
---|
453 | // Please note that as per C++ rules, implicitly casting a Value to a std::string won't work.
|
---|
454 | // This is because it could use the int/float/double/bool operators as well. So to assign a
|
---|
455 | // Value to a std::string you can either do:
|
---|
456 | // my_string = (std::string)my_value
|
---|
457 | // Or you can now do:
|
---|
458 | // my_string = my_value.ToString();
|
---|
459 | //
|
---|
460 | operator int() const;
|
---|
461 | operator float() const;
|
---|
462 | operator double() const;
|
---|
463 | operator bool() const;
|
---|
464 | operator std::string() const;
|
---|
465 | operator Object() const;
|
---|
466 | operator Array() const;
|
---|
467 |
|
---|
468 | // Returns 1 for anything not an Array/ObjectVal
|
---|
469 | size_t size() const;
|
---|
470 |
|
---|
471 | // Resets the state back to default, aka NULLVal
|
---|
472 | void Clear();
|
---|
473 |
|
---|
474 | };
|
---|
475 |
|
---|
476 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
---|
477 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
---|
478 | // Converts a JSON Object or Array instance into a JSON string representing it. RETURNS EMPTY STRING ON ERROR.
|
---|
479 | // As per JSON specification, a JSON data structure must be an array or an object. Thus, you must either pass in a
|
---|
480 | // json::Array, json::Object, or a json::Value that has an Array or Object as its underlying type.
|
---|
481 | std::string Serialize(const Value& obj);
|
---|
482 |
|
---|
483 | // If there is an error, Value will be NULLVal. Pass in a valid JSON string (such as one returned from Serialize, or obtained
|
---|
484 | // elsewhere) to receive a Value in return that represents the JSON structure. Check the type of Value by calling GetType().
|
---|
485 | // It will be ObjectVal or ArrayVal (or NULLVal if invalid JSON). The Value class contains the operator [] for indexing in the
|
---|
486 | // case that the underlying type is an object or array. You may, if you prefer, create an object or array from the Value returned
|
---|
487 | // by this method by simply passing it into the constructor.
|
---|
488 | Value Deserialize(const std::string& str);
|
---|
489 |
|
---|
490 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
---|
491 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
---|
492 | inline bool operator ==(const Object& lhs, const Object& rhs)
|
---|
493 | {
|
---|
494 | return lhs.mValues == rhs.mValues;
|
---|
495 | }
|
---|
496 |
|
---|
497 | inline bool operator <(const Object& lhs, const Object& rhs)
|
---|
498 | {
|
---|
499 | return lhs.mValues < rhs.mValues;
|
---|
500 | }
|
---|
501 |
|
---|
502 | inline bool operator ==(const Array& lhs, const Array& rhs)
|
---|
503 | {
|
---|
504 | return lhs.mValues == rhs.mValues;
|
---|
505 | }
|
---|
506 |
|
---|
507 | inline bool operator <(const Array& lhs, const Array& rhs)
|
---|
508 | {
|
---|
509 | return lhs.mValues < rhs.mValues;
|
---|
510 | }
|
---|
511 |
|
---|
512 | /* When comparing different numeric types, this method works the same as if you compared different numeric types
|
---|
513 | on your own. Thus it performs the same as if you, for example, did this:
|
---|
514 |
|
---|
515 | int a = 1;
|
---|
516 | float b = 1.1f;
|
---|
517 | bool equivalent = a == b;
|
---|
518 |
|
---|
519 | The same logic applies to the other comparison operators.
|
---|
520 | */
|
---|
521 | inline bool operator ==(const Value& lhs, const Value& rhs)
|
---|
522 | {
|
---|
523 | if ((lhs.mValueType != rhs.mValueType) && !lhs.IsNumeric() && !rhs.IsNumeric())
|
---|
524 | return false;
|
---|
525 |
|
---|
526 | switch (lhs.mValueType)
|
---|
527 | {
|
---|
528 | case StringVal : return lhs.mStringVal == rhs.mStringVal;
|
---|
529 |
|
---|
530 | case IntVal : if (rhs.GetType() == FloatVal)
|
---|
531 | return lhs.mIntVal == rhs.mFloatVal;
|
---|
532 | else if (rhs.GetType() == DoubleVal)
|
---|
533 | return lhs.mIntVal == rhs.mDoubleVal;
|
---|
534 | else if (rhs.GetType() == IntVal)
|
---|
535 | return lhs.mIntVal == rhs.mIntVal;
|
---|
536 | else
|
---|
537 | return false;
|
---|
538 |
|
---|
539 | case FloatVal : if (rhs.GetType() == FloatVal)
|
---|
540 | return lhs.mFloatVal == rhs.mFloatVal;
|
---|
541 | else if (rhs.GetType() == DoubleVal)
|
---|
542 | return lhs.mFloatVal == rhs.mDoubleVal;
|
---|
543 | else if (rhs.GetType() == IntVal)
|
---|
544 | return lhs.mFloatVal == rhs.mIntVal;
|
---|
545 | else
|
---|
546 | return false;
|
---|
547 |
|
---|
548 |
|
---|
549 | case DoubleVal : if (rhs.GetType() == FloatVal)
|
---|
550 | return lhs.mDoubleVal == rhs.mFloatVal;
|
---|
551 | else if (rhs.GetType() == DoubleVal)
|
---|
552 | return lhs.mDoubleVal == rhs.mDoubleVal;
|
---|
553 | else if (rhs.GetType() == IntVal)
|
---|
554 | return lhs.mDoubleVal == rhs.mIntVal;
|
---|
555 | else
|
---|
556 | return false;
|
---|
557 |
|
---|
558 | case BoolVal : return lhs.mBoolVal == rhs.mBoolVal;
|
---|
559 |
|
---|
560 | case ObjectVal : return lhs.mObjectVal == rhs.mObjectVal;
|
---|
561 |
|
---|
562 | case ArrayVal : return lhs.mArrayVal == rhs.mArrayVal;
|
---|
563 |
|
---|
564 | default:
|
---|
565 | return true;
|
---|
566 | }
|
---|
567 | }
|
---|
568 |
|
---|
569 | inline bool operator <(const Value& lhs, const Value& rhs)
|
---|
570 | {
|
---|
571 | if ((lhs.mValueType != rhs.mValueType) && !lhs.IsNumeric() && !rhs.IsNumeric())
|
---|
572 | return false;
|
---|
573 |
|
---|
574 | switch (lhs.mValueType)
|
---|
575 | {
|
---|
576 | case StringVal : return lhs.mStringVal < rhs.mStringVal;
|
---|
577 |
|
---|
578 | case IntVal : if (rhs.GetType() == FloatVal)
|
---|
579 | return lhs.mIntVal < rhs.mFloatVal;
|
---|
580 | else if (rhs.GetType() == DoubleVal)
|
---|
581 | return lhs.mIntVal < rhs.mDoubleVal;
|
---|
582 | else if (rhs.GetType() == IntVal)
|
---|
583 | return lhs.mIntVal < rhs.mIntVal;
|
---|
584 | else
|
---|
585 | return false;
|
---|
586 |
|
---|
587 | case FloatVal : if (rhs.GetType() == FloatVal)
|
---|
588 | return lhs.mFloatVal < rhs.mFloatVal;
|
---|
589 | else if (rhs.GetType() == DoubleVal)
|
---|
590 | return lhs.mFloatVal < rhs.mDoubleVal;
|
---|
591 | else if (rhs.GetType() == IntVal)
|
---|
592 | return lhs.mFloatVal < rhs.mIntVal;
|
---|
593 | else
|
---|
594 | return false;
|
---|
595 |
|
---|
596 | case DoubleVal : if (rhs.GetType() == FloatVal)
|
---|
597 | return lhs.mDoubleVal < rhs.mFloatVal;
|
---|
598 | else if (rhs.GetType() == DoubleVal)
|
---|
599 | return lhs.mDoubleVal < rhs.mDoubleVal;
|
---|
600 | else if (rhs.GetType() == IntVal)
|
---|
601 | return lhs.mDoubleVal < rhs.mIntVal;
|
---|
602 | else
|
---|
603 | return false;
|
---|
604 |
|
---|
605 | case BoolVal : return lhs.mBoolVal < rhs.mBoolVal;
|
---|
606 |
|
---|
607 | case ObjectVal : return lhs.mObjectVal < rhs.mObjectVal;
|
---|
608 |
|
---|
609 | case ArrayVal : return lhs.mArrayVal < rhs.mArrayVal;
|
---|
610 |
|
---|
611 | default:
|
---|
612 | return true;
|
---|
613 | }
|
---|
614 | }
|
---|
615 | }
|
---|
616 |
|
---|
617 | #endif //__SUPER_EASY_JSON_H__ |
---|