-
-
Notifications
You must be signed in to change notification settings - Fork 4
/
jsonobject.hpp
294 lines (223 loc) · 11.6 KB
/
jsonobject.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
// SPDX-License-Identifier: GPL-3.0-or-later
//
// Copyright (c) 2013-2023 plan44.ch / Lukas Zeller, Zurich, Switzerland
//
// Author: Lukas Zeller <luz@plan44.ch>
//
// This file is part of p44utils.
//
// p44utils is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// p44utils is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with p44utils. If not, see <http://www.gnu.org/licenses/>.
//
#ifndef __p44utils__jsonobject__
#define __p44utils__jsonobject__
#include "p44utils_common.hpp"
#if P44_BUILD_DIGI
#include "json.h"
#else
#include <json-c/json.h>
#endif
using namespace std;
namespace p44 {
class JsonError : public Error
{
public:
// Errors
typedef enum json_tokener_error ErrorCodes;
static const char *domain() { return "JsonObject"; }
virtual const char *getErrorDomain() const { return JsonError::domain(); };
JsonError(ErrorCodes aError) : Error(ErrorCode(aError), json_tokener_error_desc(aError)) {};
};
class JsonObject;
/// shared pointer for JSON object
typedef boost::intrusive_ptr<JsonObject> JsonObjectPtr;
/// wrapper around json-c / libjson0 object
class JsonObject : public P44Obj
{
struct json_object *mJson_obj; ///< the json-c object
struct lh_entry *mNextEntryP; ///< iterator pointer for resetKeyIteration()/nextKeyValue()
/// construct object as wrapper of json-c json_object.
/// @param aObjPassingOwnership json_object, ownership is passed into this JsonObject, caller looses ownership!
JsonObject(struct json_object *aObjPassingOwnership);
/// construct empty object
JsonObject();
public:
/// destructor, releases internally kept json_object (which is possibly owned by other objects)
virtual ~JsonObject();
/// copy constructor
JsonObject(const JsonObject& aObj);
/// assignment operator
JsonObject& operator=(const JsonObject& aObj);
/// factory to return smart pointer to new wrapper of a newly created json_object
/// @param aObjPassingOwnership json_object, ownership is passed into this JsonObject, caller looses ownership!
static JsonObjectPtr newObj(struct json_object *aObjPassingOwnership);
/// get type
/// @return type code
json_type type() const;
/// check type
/// @param aRefType type to check for
/// @return true if object matches given type
bool isType(json_type aRefType) const;
/// return JSON string representation
/// @param aFlags formatting options, see JSON_C_TO_STRING_PRETTY and other constants
/// @return JSON C string representation (valid as long as object exists)
const char *json_c_str(int aFlags=0);
/// return JSON string representation
/// @param aFlags formatting options, see JSON_C_TO_STRING_PRETTY and other constants
/// @return JSON string representation of object.
string json_str(int aFlags=0);
/// Convenience method: return JSON string representation of passed object, which may be NULL
/// @param aFlags formatting options, see JSON_C_TO_STRING_PRETTY and other constants
/// @return JSON C string representation of json aJsonObj, or "<none>" if aJsonObj is NULL
static const char* text(JsonObjectPtr aJsonObj, int aFlags=0);
/// Note: should only be used to pass object to other json-c native APIs
/// Note: Ownership of the jsonobject remains with this JsonObject
/// @return pointer the embedded json-c object structure
const struct json_object *jsoncObj() const { return mJson_obj; }
/// add object for key
/// @param aKey name of key
/// @param aObj object to store in field named aKey
void add(const char* aKey, JsonObjectPtr aObj);
/// get object by key
/// @param aKey key of object
/// @return the value of the object
/// @note to distinguish between having no such key and having the key with
/// a NULL object, use get(aKey,aJsonObject) instead
JsonObjectPtr get(const char *aKey);
/// get object by key
/// @param aKey key of object
/// @param aJsonObject will be set to the value of the key when return value is true
/// @param aIgnoreNullValues if set (default since 2022-11-24, but not before!), existing keys with
/// NULL values will be ignored, that is, return false - as if the key would not exist.
/// In this mode the function returning true guarantees that aJsonObject is not nullPtr,
/// so no testing is needed before trying to extract a value from it.
/// If not set, the method always returns true when the key exists, and aJsonObject will
/// be nullPtr when the key's value is NULL.
/// @return true if key exists and (only if aIgnoreNullValues is set) has a non-null value.
bool get(const char *aKey, JsonObjectPtr &aJsonObject, bool aIgnoreNullValues = true);
/// get object's string value by key
/// @return NULL if key does not exists or actually has NULL value, string object otherwise
/// @note the returned C string pointer is valid only as long as the object is not deleted
const char *getCString(const char *aKey);
/// delete object by key
/// @param aKey key of field to delete
void del(const char *aKey);
/// get array length
/// @return length of array. Returns 0 for empty arrays and all non-array objects
int arrayLength() const;
/// append to array
/// @param aObj object to append to the array
void arrayAppend(JsonObjectPtr aObj);
/// get from a specific position in the array
/// @param aAtIndex index position to return value for
/// @return NULL pointer if element does not exist, value otherwise
JsonObjectPtr arrayGet(int aAtIndex);
/// put at specific position in array
/// @param aAtIndex index position to put value to (overwriting existing value at that position)
/// @param aObj object to store in the array
void arrayPut(int aAtIndex, JsonObjectPtr aObj);
#if !REDUCED_FOOTPRINT
/// delete element(s) at specific position in array
/// @param aAtIndex index position of first element to delete
/// @param aNumElements number of elements to delete
void arrayDel(int aAtIndex, int aNumElements = 1);
#endif // REDUCED_FOOTPRINT
/// reset object iterator
/// @return false if object cannot be iterated
bool resetKeyIteration();
/// get next child object's key and value
/// @param aKey will be assigned the key (name) of the child object
/// @param aValue will be assigned the child object
/// @return false if there are no more key/values (aKey and aValue unchanged)
bool nextKeyValue(string &aKey, JsonObjectPtr &aValue);
/// get number of keys in this object
/// @return number of keys. Returns 0 for empty objects and all non-objects
int numKeys();
/// get key/value by index
/// @param aIndex index into object (internal, non-predictable order)
/// @param aKey will be assigned the key (name) of the child object
/// @param aValueP if not NULL, will be assigned the child object
/// @return false if there is no object with the specified aIndex
bool keyValueByIndex(int aIndex, string &aKey, JsonObjectPtr* aValueP = NULL);
/// @return new empty object
static JsonObjectPtr newObj();
/// @return create new NULL object (does not embed a real JSON-C object, just a NULL pointer)
static JsonObjectPtr newNull();
/// create new object from text
/// @param aJsonText text to be read as JSON
/// @param aMaxChars max chars to read from aJsonText, or -1 to read entire C string (until NUL terminator is found)
/// @param aErrorP where to store parsing error objects, or NULL if no error return is needed
/// @param aAllowCComments if set, C-Style comments /* */ are allowed withing JSON text (not conformant to JSON specs)
/// @param aParsedCharsP where to store the number of chars parsed from aJsonText, or NULL if not needed
/// @return new object or NULL if aJsonText parsing was not succesful
static JsonObjectPtr objFromText(const char *aJsonText, ssize_t aMaxChars = -1, ErrorPtr *aErrorP = NULL, bool aAllowCComments = false, ssize_t* aParsedCharsP = NULL);
/// create new object from text file
/// @param aJsonFilePath path of file to read as JSON
/// @param aErrorP where to store parsing error objects, or NULL if no error return is needed
/// @param aAllowCComments if set, C-Style comments /* */ are allowed withing JSON text (not conformant to JSON specs)
/// @return new object or NULL if aJsonText parsing was not succesful
static JsonObjectPtr objFromFile(const char *aJsonFilePath, ErrorPtr *aErrorP = NULL, bool aAllowCComments = false);
/// save object to text file
/// @param aJsonFilePath path of file to (over)write with text representation of this JSON object
/// @param aFlags formatting options, see JSON_C_TO_STRING_PRETTY and other constants
/// @return ok or error
ErrorPtr saveToFile(const char *aJsonFilePath, int aFlags = 0);
/// @return new array object
static JsonObjectPtr newArray();
/// @return new boolean JSON object
static JsonObjectPtr newBool(bool aBool);
/// @return boolean value
bool boolValue() const;
/// create int JSON object
/// @param aInt32 32 bit integer number
static JsonObjectPtr newInt32(int32_t aInt32);
/// create int JSON object
/// @param aInt64 64 bit integer number
static JsonObjectPtr newInt64(int64_t aInt64);
/// @return int32 value
int32_t int32Value() const;
/// @return int64 value
int64_t int64Value() const;
/// @return double JSON object
/// @param aDouble double float number
static JsonObjectPtr newDouble(double aDouble);
/// @return double value
double doubleValue() const;
/// Create new JSON string object or no object from C string
/// @param aCStr C string to make JSON string of, can be NULL to create no object
/// @return new JSON string object or NULL if aCStr is NULL
static JsonObjectPtr newString(const char *aCStr);
/// Create new JSON string object or no object from part of C string
/// @param aCStr C string to take characters from for JSON string, can be NULL to create no object
/// @param aLen max number of characters to take from aCStr
/// @return new JSON string object or NULL if aCStr is NULL
static JsonObjectPtr newString(const char *aCStr, size_t aLen);
/// @return new JSON string object
/// @param aString string to make JSON string of
/// @param aEmptyIsNull if set, and aString is empty, NULL is returned
/// @return new JSON string object or NULL if aString is empty and aEmptyIsNull is set
static JsonObjectPtr newString(const string &aString, bool aEmptyIsNull = false);
/// @return value of object as string
const char* c_strValue() const;
/// @return length of value of object as string
size_t stringLength() const;
/// @return value of object as string
string stringValue() const;
/// @return value of object as lowercase string
string lowercaseStringValue() const;
/// wrap a value in an object as the value of the named field
/// @param the name of the field the current object should have in the wrapper object
JsonObjectPtr wrapAs(const string aFieldName);
};
} // namespace
#endif /* defined(__p44utils__jsonobject__) */