Ocean
Loading...
Searching...
No Matches
JSONParser.h
Go to the documentation of this file.
1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8#ifndef META_OCEAN_IO_JSON_PARSER_H
9#define META_OCEAN_IO_JSON_PARSER_H
10
11#include "ocean/io/IO.h"
12#include "ocean/io/Scanner.h"
13
14#include <memory>
15#include <variant>
16
17namespace Ocean
18{
19
20namespace IO
21{
22
23/**
24 * This class implements a JSON parser using the Scanner.
25 * @ingroup io
26 */
27class OCEAN_IO_EXPORT JSONParser
28{
29 public:
30
31 /**
32 * This class implements a JSON value that can hold different JSON types.
33 */
34 class OCEAN_IO_EXPORT JSONValue
35 {
36 public:
37
38 /**
39 * Definition of different JSON value types.
40 */
41 enum Type : uint32_t
42 {
43 /// Invalid/uninitialized value.
44 TYPE_INVALID = 0u,
45 /// Null value.
47 /// Boolean value.
49 /// Number value.
51 /// String value.
53 /// Array value.
55 /// Object value.
56 TYPE_OBJECT
57 };
58
59 /**
60 * Definition of a JSON array (vector of JSONValue).
61 */
62 using Array = std::vector<JSONValue>;
63
64 /**
65 * Definition of a JSON object (map of string keys to JSONValue).
66 */
67 using ObjectMap = std::unordered_map<std::string, JSONValue>;
68
69 protected:
70
71 /**
72 * Definition of a unique pointer holding an array.
73 */
74 using UniqueArray = std::unique_ptr<Array>;
75
76 /**
77 * Definition of a unique pointer holding an object.
78 */
79 using UniqueObjectMap = std::unique_ptr<ObjectMap>;
80
81 public:
82
83 /**
84 * Creates an invalid JSON value.
85 */
86 JSONValue() = default;
87
88 /**
89 * Copy constructor.
90 * @param other The value to copy
91 */
92 JSONValue(const JSONValue& other);
93
94 /**
95 * Move constructor.
96 * @param other The value to move
97 */
98 JSONValue(JSONValue&& other) = default;
99
100 /**
101 * Creates a null JSON value.
102 * @param value Must be nullptr
103 */
104 explicit JSONValue(std::nullptr_t value);
105
106 /**
107 * Creates a boolean JSON value.
108 * @param value The boolean value
109 */
110 explicit JSONValue(bool value);
111
112 /**
113 * Creates a number JSON value.
114 * @param value The number value
115 */
116 explicit JSONValue(double value);
117
118 /**
119 * Creates a string JSON value.
120 * @param value The string value
121 */
122 explicit JSONValue(const std::string& value);
123
124 /**
125 * Creates a string JSON value.
126 * @param value The string value
127 */
128 explicit JSONValue(std::string&& value);
129
130 /**
131 * Creates an array JSON value.
132 * @param value The array value
133 */
134 explicit JSONValue(const Array& value);
135
136 /**
137 * Creates an array JSON value.
138 * @param value The array value
139 */
140 explicit JSONValue(Array&& value);
141
142 /**
143 * Creates an object JSON value.
144 * @param value The object value
145 */
146 explicit JSONValue(const ObjectMap& value);
147
148 /**
149 * Creates an object JSON value.
150 * @param value The object value
151 */
152 explicit JSONValue(ObjectMap&& value);
153
154 /**
155 * Returns the type of this JSON value.
156 * @return The value type
157 */
158 inline Type type() const;
159
160 /**
161 * Returns whether this value is null.
162 * @return True, if so
163 */
164 inline bool isNull() const;
165
166 /**
167 * Returns whether this value is a boolean.
168 * @return True, if so
169 */
170 inline bool isBoolean() const;
171
172 /**
173 * Returns whether this value is a number.
174 * @return True, if so
175 */
176 inline bool isNumber() const;
177
178 /**
179 * Returns whether this value is a string.
180 * @return True, if so
181 */
182 inline bool isString() const;
183
184 /**
185 * Returns whether this value is an array.
186 * @return True, if so
187 */
188 inline bool isArray() const;
189
190 /**
191 * Returns whether this value is an object.
192 * @return True, if so
193 */
194 inline bool isObject() const;
195
196 /**
197 * Returns the boolean value.
198 * @return The boolean value, false if not a boolean
199 */
200 bool boolean() const;
201
202 /**
203 * Returns the number value.
204 * @return The number value, 0.0 if not a number
205 */
206 double number() const;
207
208 /**
209 * Returns the string value.
210 * @return The string value, empty if not a string
211 */
212 const std::string& string() const;
213
214 /**
215 * Returns the array value.
216 * @return The array value, empty if not an array
217 */
218 const Array& array() const;
219
220 /**
221 * Returns the object value.
222 * @return The object value, empty if not an object
223 */
224 const ObjectMap& object() const;
225
226 /**
227 * Extracts a string value from this object by key.
228 * @param key The key to look up
229 * @return Pointer to the string value, nullptr if this is not an object, key not found, or value is not a string
230 */
231 const std::string* stringFromObject(const std::string& key) const;
232
233 /**
234 * Extracts a number value from this object by key.
235 * @param key The key to look up
236 * @return Pointer to the number value, nullptr if this is not an object, key not found, or value is not a number
237 */
238 const double* numberFromObject(const std::string& key) const;
239
240 /**
241 * Extracts a boolean value from this object by key.
242 * @param key The key to look up
243 * @return Pointer to the boolean value, nullptr if this is not an object, key not found, or value is not a boolean
244 */
245 const bool* booleanFromObject(const std::string& key) const;
246
247 /**
248 * Extracts an array value from this object by key.
249 * @param key The key to look up
250 * @return Pointer to the array value, nullptr if this is not an object, key not found, or value is not an array
251 */
252 const Array* arrayFromObject(const std::string& key) const;
253
254 /**
255 * Extracts an object value from this object by key.
256 * @param key The key to look up
257 * @return Pointer to the object value, nullptr if this is not an object, key not found, or value is not an object
258 */
259 const ObjectMap* objectFromObject(const std::string& key) const;
260
261 /**
262 * Extracts a JSONValue from an object by key.
263 * @param key The key to look up
264 * @return Pointer to the JSONValue, nullptr if this is not an object or key not found
265 */
266 const JSONValue* valueFromObject(const std::string& key) const;
267
268 /**
269 * Returns whether this value is valid.
270 * @return True, if so
271 */
272 inline bool isValid() const;
273
274 /**
275 * Returns whether this value is valid.
276 * @return True, if so
277 */
278 explicit inline operator bool() const;
279
280 /**
281 * Copy assignment operator.
282 * @param other The value to copy
283 * @return Reference to this object
284 */
286
287 /**
288 * Move assignment operator.
289 * @param other The value to move
290 * @return Reference to this object
291 */
292 JSONValue& operator=(JSONValue&& other) = default;
293
294 protected:
295
296 /// The type of this JSON value.
297 Type type_ = TYPE_INVALID;
298
299 /// The value data.
300 std::variant<std::monostate, std::nullptr_t, bool, double, std::string, UniqueArray, UniqueObjectMap> data_;
301 };
302
303 protected:
304
305 /**
306 * This class implements a JSON scanner that extends the base Scanner class.
307 * It registers JSON-specific keywords and symbols.
308 */
309 class OCEAN_IO_EXPORT JSONScanner : public Scanner
310 {
311 public:
312
313 /**
314 * Definition of JSON symbol IDs.
315 */
316 enum SymbolId : uint32_t
317 {
318 /// Left brace '{'.
319 SYMBOL_LEFT_BRACE = 0u,
320 /// Right brace '}'.
322 /// Left bracket '['.
324 /// Right bracket ']'.
326 /// Colon ':'.
328 /// Comma ','.
329 SYMBOL_COMMA
330 };
331
332 /**
333 * Definition of JSON keyword IDs.
334 */
335 enum KeywordId : uint32_t
336 {
337 /// Keyword 'true'.
338 KEYWORD_TRUE = 0u,
339 /// Keyword 'false'.
341 /// Keyword 'null'.
342 KEYWORD_NULL
343 };
344
345 public:
346
347 /**
348 * Creates a new JSON scanner using a stream as input.
349 * @param stream The stream to be used as input
350 * @param progress Optional resulting scanner progress in percent, with range [0, 1]
351 * @param cancel Optional scanner cancel flag
352 */
353 explicit JSONScanner(const std::shared_ptr<std::istream>& stream, float* progress = nullptr, bool* cancel = nullptr);
354
355 /**
356 * Creates a new JSON scanner using a file or a memory buffer as input.
357 * @param filename The name of the file to be used as input, `buffer` must be empty
358 * @param buffer The buffer to be used as input, `filename` must be empty
359 * @param progress Optional resulting scanner progress in percent, with range [0, 1]
360 * @param cancel Optional scanner cancel flag
361 */
362 JSONScanner(const std::string& filename, const std::string& buffer, float* progress = nullptr, bool* cancel = nullptr);
363
364 /**
365 * Creates a new JSON scanner using a file or a memory buffer as input.
366 * @param filename The name of the file to be used as input, `buffer` must be empty
367 * @param buffer The buffer to be used as input, `filename` must be empty
368 * @param progress Optional resulting scanner progress in percent, with range [0, 1]
369 * @param cancel Optional scanner cancel flag
370 */
371 JSONScanner(const std::string& filename, std::string&& buffer, float* progress = nullptr, bool* cancel = nullptr);
372
373 protected:
374
375 /**
376 * Initializes the JSON scanner by registering keywords and symbols.
377 */
379 };
380
381 public:
382
383 /**
384 * Parses JSON from a stream.
385 * @param stream The stream containing JSON data
386 * @param strict True, to enforce strict JSON parsing (no trailing commas); False, to allow lenient parsing
387 * @param errorMessage Optional resulting error message
388 * @return The parsed JSON value, invalid on error
389 */
390 static JSONValue parse(const std::shared_ptr<std::istream>& stream, const bool strict = false, std::string* errorMessage = nullptr);
391
392 /**
393 * Parses JSON from a file or buffer.
394 * @param filename The name of the file to parse, `buffer` must be empty
395 * @param buffer The buffer to parse, `filename` must be empty
396 * @param strict True, to enforce strict JSON parsing (no trailing commas); False, to allow lenient parsing
397 * @param errorMessage Optional resulting error message
398 * @return The parsed JSON value, invalid on error
399 */
400 static JSONValue parse(const std::string& filename, const std::string& buffer, const bool strict = false, std::string* errorMessage = nullptr);
401
402 /**
403 * Parses JSON from a file or buffer.
404 * @param filename The name of the file to parse, `buffer` must be empty
405 * @param buffer The buffer to parse, `filename` must be empty
406 * @param strict True, to enforce strict JSON parsing (no trailing commas); False, to allow lenient parsing
407 * @param errorMessage Optional resulting error message
408 * @return The parsed JSON value, invalid on error
409 */
410 static JSONValue parse(const std::string& filename, std::string&& buffer, const bool strict = false, std::string* errorMessage = nullptr);
411
412 protected:
413
414 /**
415 * Parses a JSON value.
416 * @param scanner The JSON scanner
417 * @param strict True, to enforce strict JSON parsing (no trailing commas); False, to allow lenient parsing
418 * @param errorMessage Optional resulting error message
419 * @return The parsed JSON value, invalid on error
420 */
421 static JSONValue parseValue(JSONScanner& scanner, const bool strict, std::string* errorMessage);
422
423 /**
424 * Parses a JSON object.
425 * @param scanner The JSON scanner
426 * @param strict True, to enforce strict JSON parsing (no trailing commas); False, to allow lenient parsing
427 * @param errorMessage Optional resulting error message
428 * @return The parsed JSON object value, invalid on error
429 */
430 static JSONValue parseObject(JSONScanner& scanner, const bool strict, std::string* errorMessage);
431
432 /**
433 * Parses a JSON array.
434 * @param scanner The JSON scanner
435 * @param strict True, to enforce strict JSON parsing (no trailing commas); False, to allow lenient parsing
436 * @param errorMessage Optional resulting error message
437 * @return The parsed JSON array value, invalid on error
438 */
439 static JSONValue parseArray(JSONScanner& scanner, const bool strict, std::string* errorMessage);
440
441 /**
442 * Creates an error message with line and column information.
443 * @param scanner The scanner with position information
444 * @param message The error message
445 * @return The formatted error message
446 */
447 static std::string createErrorMessage(const JSONScanner& scanner, const std::string& message);
448};
449
454
456{
457 return type_ == TYPE_NULL;
458}
459
461{
462 return type_ == TYPE_BOOLEAN;
463}
464
466{
467 return type_ == TYPE_NUMBER;
468}
469
471{
472 return type_ == TYPE_STRING;
473}
474
476{
477 return type_ == TYPE_ARRAY;
478}
479
481{
482 return type_ == TYPE_OBJECT;
483}
484
486{
487 return type_ != TYPE_INVALID;
488}
489
490inline JSONParser::JSONValue::operator bool() const
491{
492 return isValid();
493}
494
495}
496
497}
498
499#endif // META_OCEAN_IO_JSON_PARSER_H
This class implements a JSON scanner that extends the base Scanner class.
Definition JSONParser.h:310
JSONScanner(const std::shared_ptr< std::istream > &stream, float *progress=nullptr, bool *cancel=nullptr)
Creates a new JSON scanner using a stream as input.
JSONScanner(const std::string &filename, const std::string &buffer, float *progress=nullptr, bool *cancel=nullptr)
Creates a new JSON scanner using a file or a memory buffer as input.
JSONScanner(const std::string &filename, std::string &&buffer, float *progress=nullptr, bool *cancel=nullptr)
Creates a new JSON scanner using a file or a memory buffer as input.
void initialize()
Initializes the JSON scanner by registering keywords and symbols.
KeywordId
Definition of JSON keyword IDs.
Definition JSONParser.h:336
@ KEYWORD_FALSE
Keyword 'false'.
Definition JSONParser.h:340
SymbolId
Definition of JSON symbol IDs.
Definition JSONParser.h:317
@ SYMBOL_LEFT_BRACKET
Left bracket '['.
Definition JSONParser.h:323
@ SYMBOL_RIGHT_BRACE
Right brace '}'.
Definition JSONParser.h:321
@ SYMBOL_COLON
Colon ':'.
Definition JSONParser.h:327
@ SYMBOL_RIGHT_BRACKET
Right bracket ']'.
Definition JSONParser.h:325
This class implements a JSON value that can hold different JSON types.
Definition JSONParser.h:35
JSONValue & operator=(JSONValue &&other)=default
Move assignment operator.
bool isNumber() const
Returns whether this value is a number.
Definition JSONParser.h:465
bool isString() const
Returns whether this value is a string.
Definition JSONParser.h:470
const std::string & string() const
Returns the string value.
JSONValue(JSONValue &&other)=default
Move constructor.
const Array * arrayFromObject(const std::string &key) const
Extracts an array value from this object by key.
JSONValue()=default
Creates an invalid JSON value.
JSONValue(double value)
Creates a number JSON value.
const Array & array() const
Returns the array value.
const bool * booleanFromObject(const std::string &key) const
Extracts a boolean value from this object by key.
double number() const
Returns the number value.
JSONValue(const Array &value)
Creates an array JSON value.
bool isNull() const
Returns whether this value is null.
Definition JSONParser.h:455
bool isObject() const
Returns whether this value is an object.
Definition JSONParser.h:480
bool isBoolean() const
Returns whether this value is a boolean.
Definition JSONParser.h:460
const JSONValue * valueFromObject(const std::string &key) const
Extracts a JSONValue from an object by key.
JSONValue(ObjectMap &&value)
Creates an object JSON value.
bool boolean() const
Returns the boolean value.
JSONValue(bool value)
Creates a boolean JSON value.
const ObjectMap & object() const
Returns the object value.
std::variant< std::monostate, std::nullptr_t, bool, double, std::string, UniqueArray, UniqueObjectMap > data_
The value data.
Definition JSONParser.h:300
const ObjectMap * objectFromObject(const std::string &key) const
Extracts an object value from this object by key.
Type type_
The type of this JSON value.
Definition JSONParser.h:297
std::unordered_map< std::string, JSONValue > ObjectMap
Definition of a JSON object (map of string keys to JSONValue).
Definition JSONParser.h:67
std::vector< JSONValue > Array
Definition of a JSON array (vector of JSONValue).
Definition JSONParser.h:62
std::unique_ptr< Array > UniqueArray
Definition of a unique pointer holding an array.
Definition JSONParser.h:74
JSONValue(std::nullptr_t value)
Creates a null JSON value.
JSONValue(Array &&value)
Creates an array JSON value.
const double * numberFromObject(const std::string &key) const
Extracts a number value from this object by key.
JSONValue & operator=(const JSONValue &other)
Copy assignment operator.
JSONValue(std::string &&value)
Creates a string JSON value.
bool isArray() const
Returns whether this value is an array.
Definition JSONParser.h:475
bool isValid() const
Returns whether this value is valid.
Definition JSONParser.h:485
Type
Definition of different JSON value types.
Definition JSONParser.h:42
@ TYPE_BOOLEAN
Boolean value.
Definition JSONParser.h:48
@ TYPE_NUMBER
Number value.
Definition JSONParser.h:50
@ TYPE_NULL
Null value.
Definition JSONParser.h:46
@ TYPE_STRING
String value.
Definition JSONParser.h:52
@ TYPE_ARRAY
Array value.
Definition JSONParser.h:54
JSONValue(const JSONValue &other)
Copy constructor.
JSONValue(const std::string &value)
Creates a string JSON value.
Type type() const
Returns the type of this JSON value.
Definition JSONParser.h:450
const std::string * stringFromObject(const std::string &key) const
Extracts a string value from this object by key.
std::unique_ptr< ObjectMap > UniqueObjectMap
Definition of a unique pointer holding an object.
Definition JSONParser.h:79
JSONValue(const ObjectMap &value)
Creates an object JSON value.
This class implements a JSON parser using the Scanner.
Definition JSONParser.h:28
static JSONValue parse(const std::shared_ptr< std::istream > &stream, const bool strict=false, std::string *errorMessage=nullptr)
Parses JSON from a stream.
static JSONValue parseValue(JSONScanner &scanner, const bool strict, std::string *errorMessage)
Parses a JSON value.
static JSONValue parseArray(JSONScanner &scanner, const bool strict, std::string *errorMessage)
Parses a JSON array.
static JSONValue parse(const std::string &filename, const std::string &buffer, const bool strict=false, std::string *errorMessage=nullptr)
Parses JSON from a file or buffer.
static JSONValue parseObject(JSONScanner &scanner, const bool strict, std::string *errorMessage)
Parses a JSON object.
static JSONValue parse(const std::string &filename, std::string &&buffer, const bool strict=false, std::string *errorMessage=nullptr)
Parses JSON from a file or buffer.
static std::string createErrorMessage(const JSONScanner &scanner, const std::string &message)
Creates an error message with line and column information.
This class implements a simple scanner.
Definition Scanner.h:31
The namespace covering the entire Ocean framework.
Definition Accessor.h:15