API Documentation
Loading...
Searching...
No Matches
JSONParser.h
Go to the documentation of this file.
1/*--------------------------------------------------------------------------------------------
2Copyright (c) 2019, NDEVR LLC
3tyler.parke@ndevr.org
4 __ __ ____ _____ __ __ _______
5 | \ | | | __ \ | ___|\ \ / / | __ \
6 | \ | | | | \ \ | |___ \ \ / / | |__) |
7 | . \| | | |__/ / | |___ \ V / | _ /
8 | |\ |_|_____/__|_____|___\_/____| | \ \
9 |__| \__________________________________| \__\
10
11Subject to the terms of the Enterprise+ Agreement, NDEVR hereby grants
12Licensee a limited, non-exclusive, non-transferable, royalty-free license
13(without the right to sublicense) to use the API solely for the purpose of
14Licensee's internal development efforts to develop applications for which
15the API was provided.
16
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
21INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
22PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
23FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25DEALINGS IN THE SOFTWARE.
26
27Library: Base
28File: JSONParser
29Included in API: True
30Author(s): Tyler Parke
31 *-----------------------------------------------------------------------------------------**/
32#pragma once
33#include "DLLInfo.h"
34#include <NDEVR/Scanner.h>
35#include <NDEVR/String.h>
36#include <NDEVR/Buffer.h>
37#include <NDEVR/Dictionary.h>
38#include <NDEVR/Time.h>
39namespace NDEVR
40{
41 class TranslatedString;
42 /**--------------------------------------------------------------------------------------------------
43 Class: JSONNode
44
45 \brief JavaScript Object Notation or JSON is an open - standard file format that uses human - readable text
46 to transmit data objects consisting of attribute–value pairs and array data types(or any other
47 serializable value).
48
49 It is a very common data format used for asynchronous browser–server communication,
50 including as a replacement for XML in some AJAX - style systems.
51
52 The JSONNode class serves as a container for data and it's children. Includes options to read and write
53 from streams and files.
54
55 Author: Tyler Parke
56
57 Date: 2017-11-13
58 **/
60 {
61 static const uint04 s_number_of_decimals = 10;//default number of decimals to write
62 public:
64 {
65 e_number // Stores a number (May be integer or floating point)
66 , e_array // Stores an array of values
67 , e_bool // Stores boolean true/false
68 , e_object // Stores an object, which has data, but is not a number type
69 , e_node // Is a node, storing a number of children JSON nodes
70 , e_root // Is a root node, meaning it has no parent
71 };
72 public:
73
74 /**--------------------------------------------------------------------------------------------------
75 Creates a root JSON node
76
77 Author: Tyler Parke
78
79 Date: 2017-11-19
80 **/
82
83 /**--------------------------------------------------------------------------------------------------
84 Creates a JSONNode with a given name
85
86 Author: Tyler Parke
87
88 Date: 2017-11-19
89 **/
90 protected:
91 JSONNode(const String& name);
92 /**--------------------------------------------------------------------------------------------------
93 Very basic copy constructor.
94
95 Author: Tyler Parke
96
97 Date: 2017-11-19
98 **/
99 public:
100 JSONNode(const JSONNode& node);
101
102 /**--------------------------------------------------------------------------------------------------
103 Very basic move constructor.
104
105 Author: Tyler Parke
106
107 Date: 2017-11-19
108 **/
109 JSONNode(JSONNode&& node) noexcept;
110
111 /**--------------------------------------------------------------------------------------------------
112 Creates a JSONNode by parsing it from the scanner. Scanner should be at the start of the file or
113 stream just before the opening '{'
114
115 Author: Tyler Parke
116
117 Date: 2017-11-19
118 **/
120 JSONNode(const String& node, const String& json_string);
121 /**--------------------------------------------------------------------------------------------------
122 Creates a JSONNode by parsing it from the File.
123
124 Author: Tyler Parke
125
126 Date: 2017-11-19
127 **/
129
131
132 /**--------------------------------------------------------------------------------------------------
133 Author: Tyler Parke
134
135 Date: 2017-11-19
136
137 \returns The type of the node which will give a hint as to how the contents should be written to
138 a file, or interpretted by the program
139 **/
140 NodeType type() const;
141
142 /**--------------------------------------------------------------------------------------------------
143 A no frills write routine. Useful for writing to a file.
144
145 Author: Tyler Parke
146
147 Date: 2017-11-19
148
149 Parameters:
150 stream - The stream where you want the JSON node to be written
151 **/
152 void write(String& stream) const;
153
154 /**--------------------------------------------------------------------------------------------------
155 \brief Writes the JSON structure out to a file with no frills. Same as write(String&) but for files.
156
157 Author: Tyler Parke
158
159 Date: 2017-11-19
160
161 Parameters:
162 file - The file where you want the JSON node to be written
163 **/
164 void write(File& file);
165
166 void write(std::ostream& file);
167
168 /**--------------------------------------------------------------------------------------------------
169 \brief Same as write, but adds tabs and new lines to make it easier to read, though will result in larger
170 file.
171
172 Author: Tyler Parke
173
174 Date: 2017-11-19
175
176 Parameters:
177 stream - The stream where you want the JSON node to be written
178 tab_indention - The number of tabs to place before writing data
179 **/
180 void writePretty(String& stream, const uint04 tab_indention = 0) const;
181 /**--------------------------------------------------------------------------------------------------
182 \brief Writes our structure out to a file using tabs and new lines. Same as writePretty(String&) but for files.
183
184 Author: Tyler Parke
185
186 Date: 2017-11-19
187
188 Parameters:
189 file - The file where you want the JSON node to be written
190 **/
191 void writePretty(File& file);
192 void writePretty(std::ostream& file);
193 /**--------------------------------------------------------------------------------------------------
194 Returns this object as the type specified.
195
196 Author: Tyler Parke
197
198 Date: 2017-11-19
199 **/
200 template<class t_type>
201 decltype(auto) getAs() const
202 {
203 return JSONToStringHelper<t_type>::Convert(m_value);
204 }
205
206 /**--------------------------------------------------------------------------------------------------
207 returns the child, if it exists. Is read only. Same as (*this)[child_node]
208
209 Author: Tyler Parke
210
211 Date: 2017-11-19
212
213 Parameters:
214 child_node - The name of the node you want to return. Must be an existing child node.
215 **/
216 const JSONNode& get(const String& child_node) const
217 {
218 return *m_json_children[child_node];
219 }
220 /**--------------------------------------------------------------------------------------------------
221 returns the child, if it exists. Is read only. Same as get
222
223 Author: Tyler Parke
224
225 Date: 2017-11-19
226
227 Parameters:
228 child_node - The name of the node you want to return. Must be an existing child node.
229 **/
230 const JSONNode& operator[](const String& child_node) const;
231 JSONNode& operator[](const String& child_node);
232 /**--------------------------------------------------------------------------------------------------
233 Returns the child, if it exists.
234
235 Author: Tyler Parke
236
237 Date: 2017-11-19
238
239 Parameters:
240 child_idx - The index of the node you want to return.
241 **/
242 JSONNode& operator[](const uint04& child_idx);
243 const JSONNode& operator[](const uint04& child_idx) const;
244
246 {
247 return m_sorted_json_children;
248 }
249 bool hasNode(const String& child_node) const
250 {
251 return m_json_children.hasKey(child_node);
252 }
253
254 const String& nodeName() const
255 {
256 return m_name;
257 }
258
259 void remove(const String& child_node);
260 JSONNode& createChildNode(const String& child_node, NodeType type);
261 /**--------------------------------------------------------------------------------------------------
262 A special case of the = operator for nodes. Note that this will not set the name of the node, but
263 set the contents equal to that of another
264
265 Author: Tyler Parke
266
267 Date: 2017-11-19
268 **/
270 {
271 m_value = node.m_value;
272 if (node.m_type == e_root)
273 m_type = e_node;//convert root to node
274 else
275 m_type = node.m_type;
276 for (const auto& iter : m_sorted_json_children)
277 {
278 delete iter;
279 }
280 m_sorted_json_children.clear();
281 m_json_children.clear();
282 for (const auto& iter : node.m_sorted_json_children)
283 {
284 m_sorted_json_children.add(new JSONNode(*iter));
285 if (!m_json_children.hasKey(iter->nodeName()))
286 m_json_children.add(iter->nodeName(), m_sorted_json_children.last());
287 }
288 return *this;
289 }
290
291
292 JSONNode& operator=(const String& value)
293 {
294 m_type = e_object;
295 m_value = value;
296 return *this;
297 }
298 template<class t_type>
300 {
301 m_type = e_object;
302 m_value = String(value.template as<DEGREES>());
303 return *this;
304 }
305
306 /**--------------------------------------------------------------------------------------------------
307 A special case Time equals. writes in YYYY/MM/DDTHH:mm:ss.fffZ format.
308
309 Author: Tyler Parke
310
311 Date: 2017-11-19
312 **/
313 JSONNode& operator=(const Time& time)
314 {
315 m_type = e_object;
316 m_value = time.toString(false, "YYYY/MM/DDTHH:mm:ss.fffZ");;
317 return *this;
318 }
319
320 template<class t_type, class t_allocator>
322 {
323 m_type = e_array;
324 m_value = String(buffer);
325 return *this;
326 }
327
328 template<uint01 t_dims, class t_type>
330 {
331 m_type = e_array;
332 m_value = String(buffer);
333 return *this;
334 }
335
336 /**--------------------------------------------------------------------------------------------------
337 Returns true if the node contains no information.
338
339 Author: Tyler Parke
340
341 Date: 2019-14-12
342 **/
343 [[nodiscard]] bool isEmpty() const
344 {
345 return m_value.size() == 0 && m_json_children.size() == 0;
346 }
347
348 /**--------------------------------------------------------------------------------------------------
349 A general case t_type equals. Sets the value internal and predicts the type.
350
351 Author: Tyler Parke
352
353 Date: 2017-11-19
354 **/
355 template<class t_type>
356 JSONNode& operator=(const t_type& value)
357 {
359 m_type = e_number;
361 m_type = e_bool;
363 m_type = e_array;
364 else if (ObjectInfo<t_type>::Color)//An RGBColor is converted into an array of integers {red, green, blue, alpha}
365 m_type = e_array;
366 else
367 m_type = e_object;
368 m_value = String(value);
369 return *this;
370 }
371
372 /**--------------------------------------------------------------------------------------------------
373 Returns the number of children within this node.
374
375 Author: Tyler Parke
376
377 Date: 2017-11-19
378 **/
380 {
381 return cast<uint04>(m_json_children.size());
382 }
383 //Used for parsing our children in a for/each loop
384 [[nodiscard]] decltype(auto) begin()
385 {
386 return m_json_children.begin();
387 }
388 [[nodiscard]] decltype(auto) begin() const
389 {
390 return m_json_children.begin();
391 }
392
393 [[nodiscard]] decltype(auto) end()
394 {
395 return m_json_children.end();
396 }
397 [[nodiscard]] decltype(auto) end() const
398 {
399 return m_json_children.end();
400 }
402 protected:
403 /**--------------------------------------------------------------------------------------------------
404 Reads in the next JSON item and adds it to this node's children
405
406 Parameters:
407 scan - The object tasked with reading in our data. Shold be just past the second '"' at the end of
408 the node's title at this point.
409
410 Author: Tyler Parke
411
412 Date: 2017-11-19
413
414 \returns true if there is an adjacent child next to this one, false if end of stream or no additional
415 children.
416 **/
417 bool parseJSON(Scanner& scan);
418 bool parseJSONContent(char start, Scanner& scan);
419
420 /**--------------------------------------------------------------------------------------------------
421 Reads in the next YAML item and adds it to this node's children
422
423 Parameters:
424 scan - The object tasked with reading in our data. Shold be just past the second '"' at the end of
425 the node's title at this point.
426
427 Author: Tyler Parke
428
429 Date: 2024-07-08
430
431 \returns true if there is an adjacent child next to this one, false if end of stream or no additional
432 children.
433 **/
434 bool parseYAMLContent(uint04 indentention, Scanner& scan);
435
436 /**--------------------------------------------------------------------------------------------------
437 Reads in all of the children nodes for this node and adds them to the children list
438
439 Parameters:
440 scan - The object tasked with reading in our data. Shold be just before the first '"' specifying
441 the title
442
443 Author: Tyler Parke
444
445 Date: 2017-11-19
446 **/
448
449 /**--------------------------------------------------------------------------------------------------
450 Reads in a single object type for this child.
451
452 Parameters:
453 scan - The object tasked with reading in our data. Shold be just past the first '"' specifying
454 the data
455
456 Author: Tyler Parke
457
458 Date: 2017-11-19
459 **/
460 void readData(Scanner& scan);
461
462 /**--------------------------------------------------------------------------------------------------
463 Reads in an array of items for this child.
464
465 Parameters:
466 scan - The object tasked with reading in our data. Shold be just past the first '[' specifying
467 the beginning of the array
468
469 Author: Tyler Parke
470
471 Date: 2017-11-19
472 **/
473 void readArray(Scanner& scan);
474
475 /**--------------------------------------------------------------------------------------------------
476 Writes tabs to the file
477
478 Parameters:
479 stream - Where to append the tabs
480 tab_indention - The number of tabs to write
481
482 Author: Tyler Parke
483
484 Date: 2017-11-19
485 **/
486 static void WriteTabs(String& stream, uint04 tab_indention);
487 static void ConvertToJSONString(String& string);
488 static void ConvertFromJSONString(String& string);
489 protected:
490 static TranslatedString UnexpectedCharErrorString(char current_char, const Scanner& scan);
491 static TranslatedString DuplicateChildErrorString(const String& child, const Scanner& scan);
493 protected:
495 Dictionary<String, JSONNode*> m_json_children;//The children of this node. If the node type is not e_node or e_root, this is empty
496 const String m_name; //The name of the node
497 String m_value; //The value of the node
498 NodeType m_type;// the type of the node.
499 private:
500 template<class t_type>
501 class JSONToStringHelper
502 {
503 public:
504 static t_type Convert(const String& value)
505 {
506 return value.getAs<t_type>();
507 }
508 };
509 template<class t_type>
510 class JSONToStringHelper<Angle<t_type>>
511 {
512 public:
513 static Angle<t_type> Convert(const String& value)
514 {
515 return Angle<t_type>(DEGREES, value.getAs<fltp08>());
516 }
517 };
518 template<>
519 class JSONToStringHelper<String>
520 {
521 public:
522 static const String& Convert(const String& value)
523 {
524 return value;
525 }
526 };
527 template<>
528 class JSONToStringHelper<Time>
529 {
530 public:
531 /**--------------------------------------------------------------------------------------------------
532 \brief Template specialization for time, as the format for time in JSON is not entirely specified, so we
533 make some guesses.
534
535 Author: Tyler Parke
536
537 Date: 2017-11-19
538 **/
539 static Time Convert(const String& value)
540 {
541 //There are 3 different types of times we support. As JSON does not specify a
542 //time format each of these could be valid. We will do some tests to guess which to use
543 if (value.contains('.'))//Option 1) JavaScript built-in JSON object
544 return Time(value, false, "YYYY/MM/DDTHH:mm:ss.fffZ");
545 else if (value.contains('T'))//Option 2) JavaScript built-in JSON object with no millisecond
546 return Time(value, false, "YYYY/MM/DDTHH:mm:ss");
547 uint04 sub_value = value.indexOf("Date(");//Option 3) date sub value expressed as seconds)
548 if (!IsInvalid(sub_value))
549 {
550 return Time(value.substr(sub_value + 5).getAs<uint08>() * Time::SECOND);
551 }
552 Time time_val = value.getAs<Time>();
553 lib_assert(!IsInvalid(time_val), "Could not parse time value");
554 return time_val;//Return an invalid time as we were unable to parse
555 }
556 };
557 };
558
559}
560
561
#define NDEVR_BASE_API
Definition DLLInfo.h:57
#define lib_assert(expression, message)
Definition LibAssert.h:61
The primary angle storage class for this API. Stores an angle in an optimized format.
Definition StringStream.h:540
The equivelent of std::vector but with a bit more control. The basic array unit of the library.
Definition Buffer.hpp:56
A hash-based key-value store, useful for quick associative lookups. Key features include:
Definition Dictionary.h:61
Logic for reading or writing to a file as well as navigating filesystems.
Definition File.h:48
JavaScript Object Notation or JSON is an open - standard file format that uses human - readable text ...
Definition JSONParser.h:60
void writePretty(String &stream, const uint04 tab_indention=0) const
Same as write, but adds tabs and new lines to make it easier to read, though will result in larger fi...
NodeType type() const
bool parseJSON(Scanner &scan)
Buffer< JSONNode * > m_sorted_json_children
Definition JSONParser.h:494
void write(String &stream) const
JSONNode & operator[](const uint04 &child_idx)
JSONNode(Scanner &scan)
void writePretty(File &file)
Writes our structure out to a file using tabs and new lines. Same as writePretty(String&) but for fil...
bool parseJSONContent(char start, Scanner &scan)
void remove(const String &child_node)
JSONNode(const String &node, const String &json_string)
static void ConvertFromJSONString(String &string)
JSONNode(const JSONNode &node)
JSONNode & operator=(const t_type &value)
Definition JSONParser.h:356
void writePretty(std::ostream &file)
void write(File &file)
Writes the JSON structure out to a file with no frills. Same as write(String&) but for files.
JSONNode & operator=(const String &value)
Definition JSONParser.h:292
static TranslatedString DuplicateChildErrorString(const String &child, const Scanner &scan)
JSONNode & createChildNode(const String &child_node, NodeType type)
const JSONNode & operator[](const String &child_node) const
JSONNode & operator=(const Buffer< t_type, t_allocator > &buffer)
Definition JSONParser.h:321
Dictionary< String, JSONNode * > m_json_children
Definition JSONParser.h:495
const String m_name
Definition JSONParser.h:496
JSONNode & operator=(const Time &time)
Definition JSONParser.h:313
decltype(auto) end()
Definition JSONParser.h:393
JSONNode & operator=(const JSONNode &node)
Definition JSONParser.h:269
static TranslatedString BadChildErrorString(const Scanner &scan)
JSONNode & operator[](const String &child_node)
String m_value
Definition JSONParser.h:497
JSONNode(const String &name)
void write(std::ostream &file)
static void WriteTabs(String &stream, uint04 tab_indention)
decltype(auto) getAs() const
Definition JSONParser.h:201
uint04 size()
Definition JSONParser.h:379
JSONNode & operator=(const Vector< t_dims, t_type > &buffer)
Definition JSONParser.h:329
bool hasNode(const String &child_node) const
Definition JSONParser.h:249
decltype(auto) begin()
Definition JSONParser.h:384
const String & nodeName() const
Definition JSONParser.h:254
const JSONNode & get(const String &child_node) const
Definition JSONParser.h:216
bool parseYAMLContent(uint04 indentention, Scanner &scan)
void readData(Scanner &scan)
static JSONNode ParseYAML(Scanner &scan)
static TranslatedString UnexpectedCharErrorString(char current_char, const Scanner &scan)
const JSONNode & operator[](const uint04 &child_idx) const
NodeType
Definition JSONParser.h:64
decltype(auto) begin() const
Definition JSONParser.h:388
JSONNode(JSONNode &&node) noexcept
bool isEmpty() const
Definition JSONParser.h:343
JSONNode & operator=(const Angle< t_type > &value)
Definition JSONParser.h:299
NodeType m_type
Definition JSONParser.h:498
void readArray(Scanner &scan)
void readChildrenNodes(Scanner &scan)
decltype(auto) end() const
Definition JSONParser.h:397
const Buffer< JSONNode * > & children() const
Definition JSONParser.h:245
JSONNode(File &file)
static void ConvertToJSONString(String &string)
Contains methods for easily reading objects in an ascii stream.
Definition Scanner.h:45
The core String class for the NDEVR API.
Definition String.h:69
t_type getAs() const
Converts a string into an object. To use this function an object must have overwritten StringStream<t...
Definition String.h:143
Represents a timestamp with utilities for manipulation and conversion.
Definition Time.h:54
String toString(bool get_local_time, const String &format_string) const
Converts the timestamp to a string representation. https://ndevr.org/time-patterns/.
Any text displayed to the user should be defined as a TranslatedString which allows the program to lo...
Definition TranslatedString.h:13
A fixed-size array with better performance compared to dynamic containers.
Definition Vector.hpp:60
Definition ACIColor.h:37
constexpr bool IsInvalid(const t_type &value)
Query if 'value' is valid or invalid. Invalid values should return invalid if used for calculations o...
Definition BaseFunctions.hpp:170
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
Definition BaseValues.hpp:96
double fltp08
Defines an alias representing an 8 byte floating-point number.
Definition BaseValues.hpp:149
Information about the object.
Definition ObjectInfo.h:54