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>
39 /**--------------------------------------------------------------------------------------------------
40 Namespace: Parke
41 Namespace that wraps all Logic created by Tyler Parke
42 *-----------------------------------------------------------------------------------------------**/
43namespace NDEVR
44{
45 class TranslatedString;
46 template<class t_type>
48 {
49 public:
50 static t_type Convert(const String& value)
51 {
52 return value.getAs<t_type>();
53 }
54 };
55 template<class t_type>
57 {
58 public:
59 static Angle<t_type> Convert(const String& value)
60 {
61 return Angle<t_type>(DEGREES, value.getAs<fltp08>());
62 }
63 };
64 template<>
66 {
67 public:
68 static const String& Convert(const String& value)
69 {
70 return value;
71 }
72 };
73 template<>
75 {
76 public:
77 /**--------------------------------------------------------------------------------------------------
78 \brief Template specialization for time, as the format for time in JSON is not entirely specified, so we
79 make some guesses.
80
81 Author: Tyler Parke
82
83 Date: 2017-11-19
84 *-----------------------------------------------------------------------------------------------**/
85 static Time Convert(const String& value)
86 {
87 //There are 3 different types of times we support. As JSON does not specify a
88 //time format each of these could be valid. We will do some tests to guess which to use
89 if (value.contains('.'))//Option 1) JavaScript built-in JSON object
90 return Time(value, false, "YYYY/MM/DDTHH:mm:ss.fffZ");
91 else if (value.contains('T'))//Option 2) JavaScript built-in JSON object with no millisecond
92 return Time(value, false, "YYYY/MM/DDTHH:mm:ss");
93 uint04 sub_value = value.indexOf("Date(");//Option 3) date sub value expressed as seconds)
94 if (!isNaN(sub_value))
95 {
96 return Time(value.substr(sub_value + 5).getAs<uint08>() * Time::SECOND);
97 }
98 Time time_val = value.getAs<Time>();
99 lib_assert(!isNaN(time_val), "Could not parse time value");
100 return time_val;//Return an invalid time as we were unable to parse
101 }
102 };
103 /**--------------------------------------------------------------------------------------------------
104 Class: JSONNode
105
106 \brief JavaScript Object Notation or JSON is an open - standard file format that uses human - readable text
107 to transmit data objects consisting of attribute–value pairs and array data types(or any other
108 serializable value).
109
110 It is a very common data format used for asynchronous browser–server communication,
111 including as a replacement for XML in some AJAX - style systems.
112
113 The JSONNode class serves as a container for data and it's children. Includes options to read and write
114 from streams and files.
115
116 Author: Tyler Parke
117
118 Date: 2017-11-13
119 *-----------------------------------------------------------------------------------------------**/
121 {
122 static const uint04 s_number_of_decimals = 10;//default number of decimals to write
123 public:
125 {
126 e_number // Stores a number (May be integer or floating point)
127 , e_array // Stores an array of values
128 , e_bool // Stores boolean true/false
129 , e_object // Stores an object, which has data, but is not a number type
130 , e_node // Is a node, storing a number of children JSON nodes
131 , e_root // Is a root node, meaning it has no parent
132 };
133 public:
134
135 /**--------------------------------------------------------------------------------------------------
136 Fn: JSONNode::JSONNode(const String& name)
137
138 Creates a root JSON node
139
140 Author: Tyler Parke
141
142 Date: 2017-11-19
143 *-----------------------------------------------------------------------------------------------**/
144 JSONNode();
145
146 /**--------------------------------------------------------------------------------------------------
147 Fn: JSONNode::JSONNode(const String& name)
148
149 Creates a JSONNode with a given name
150
151 Author: Tyler Parke
152
153 Date: 2017-11-19
154 *-----------------------------------------------------------------------------------------------**/
155 protected:
156 JSONNode(const String& name);
157 /**--------------------------------------------------------------------------------------------------
158 Fn: JSONNode::JSONNode(const JSONNode& node)
159
160 Very basic copy constructor.
161
162 Author: Tyler Parke
163
164 Date: 2017-11-19
165 *-----------------------------------------------------------------------------------------------**/
166 public:
167 JSONNode(const JSONNode& node);
168
169 /**--------------------------------------------------------------------------------------------------
170 Fn: JSONNode::JSONNode(const JSONNode&& node)
171
172 Very basic move constructor.
173
174 Author: Tyler Parke
175
176 Date: 2017-11-19
177 *-----------------------------------------------------------------------------------------------**/
178 JSONNode(JSONNode&& node) noexcept;
179
180 /**--------------------------------------------------------------------------------------------------
181 Fn: JSONNode::JSONNode(Scanner& scan)
182
183 Creates a JSONNode by parsing it from the scanner. Scanner should be at the start of the file or
184 stream just before the opening '{'
185
186 Author: Tyler Parke
187
188 Date: 2017-11-19
189 *-----------------------------------------------------------------------------------------------**/
190 JSONNode(Scanner& scan);
191 JSONNode(const String& node, const String& json_string);
192 /**--------------------------------------------------------------------------------------------------
193 Fn: JSONNode::JSONNode(File& scan)
194
195 Creates a JSONNode by parsing it from the File.
196
197 Author: Tyler Parke
198
199 Date: 2017-11-19
200 *-----------------------------------------------------------------------------------------------**/
201 JSONNode(File& file);
202
203 ~JSONNode();
204
205 /**--------------------------------------------------------------------------------------------------
206 Fn: NodeType JSONNode::type() const
207
208 Author: Tyler Parke
209
210 Date: 2017-11-19
211
212 Returns: The type of the node which will give a hint as to how the contents should be written to
213 a file, or interpretted by the program
214 *-----------------------------------------------------------------------------------------------**/
215 NodeType type() const;
216
217 /**--------------------------------------------------------------------------------------------------
218 Fn: void JSONNode::write(String& stream) const
219
220 A no frills write routine. Useful for writing to a file.
221
222 Author: Tyler Parke
223
224 Date: 2017-11-19
225
226 Parameters:
227 stream - The stream where you want the JSON node to be written
228 *-----------------------------------------------------------------------------------------------**/
229 void write(String& stream) const;
230
231 /**--------------------------------------------------------------------------------------------------
232 Fn: void JSONNode::write(File& file)
233
234 \brief Writes the JSON structure out to a file with no frills. Same as write(String&) but for files.
235
236 Author: Tyler Parke
237
238 Date: 2017-11-19
239
240 Parameters:
241 file - The file where you want the JSON node to be written
242 *-----------------------------------------------------------------------------------------------**/
243 void write(File& file);
244
245 void write(std::ostream& file);
246
247 /**--------------------------------------------------------------------------------------------------
248 Fn: void JSONNode::writePretty(String& stream, const uint04 tab_indention = 0) const
249
250 \brief Same as write, but adds tabs and new lines to make it easier to read, though will result in larger
251 file.
252
253 Author: Tyler Parke
254
255 Date: 2017-11-19
256
257 Parameters:
258 stream - The stream where you want the JSON node to be written
259 tab_indention - The number of tabs to place before writing data
260 *-----------------------------------------------------------------------------------------------**/
261 void writePretty(String& stream, const uint04 tab_indention = 0) const;
262 /**--------------------------------------------------------------------------------------------------
263 Fn: void JSONNode::writePretty(File& file)
264
265 \brief Writes our structure out to a file using tabs and new lines. Same as writePretty(String&) but for files.
266
267 Author: Tyler Parke
268
269 Date: 2017-11-19
270
271 Parameters:
272 file - The file where you want the JSON node to be written
273 *-----------------------------------------------------------------------------------------------**/
274 void writePretty(File& file);
275 void writePretty(std::ostream& file);
276 /**--------------------------------------------------------------------------------------------------
277 Fn: void JSONNode::getAs()
278
279 Returns this object as the type specified.
280
281 Author: Tyler Parke
282
283 Date: 2017-11-19
284 *-----------------------------------------------------------------------------------------------**/
285 template<class t_type>
286 decltype(auto) getAs() const
287 {
289 }
290
291 /**--------------------------------------------------------------------------------------------------
292 Fn: const JSONNode& JSONNode::get(const String& child_node) const
293
294 returns the child, if it exists. Is read only. Same as (*this)[child_node]
295
296 Author: Tyler Parke
297
298 Date: 2017-11-19
299
300 Parameters:
301 child_node - The name of the node you want to return. Must be an existing child node.
302 *-----------------------------------------------------------------------------------------------**/
303 const JSONNode& get(const String& child_node) const
304 {
305 return *m_json_children[child_node];
306 }
307 /**--------------------------------------------------------------------------------------------------
308 Fn: const JSONNode& JSONNode::operator[](const String& child_node) const
309
310 returns the child, if it exists. Is read only. Same as get
311
312 Author: Tyler Parke
313
314 Date: 2017-11-19
315
316 Parameters:
317 child_node - The name of the node you want to return. Must be an existing child node.
318 *-----------------------------------------------------------------------------------------------**/
319 const JSONNode& operator[](const String& child_node) const;
320 JSONNode& operator[](const String& child_node);
321 /**--------------------------------------------------------------------------------------------------
322 Fn: JSONNode& JSONNode::operator[](const uint04& child_node)
323
324 Returns the child, if it exists.
325
326 Author: Tyler Parke
327
328 Date: 2017-11-19
329
330 Parameters:
331 child_idx - The index of the node you want to return.
332 *-----------------------------------------------------------------------------------------------**/
333 JSONNode& operator[](const uint04& child_idx);
334 const JSONNode& operator[](const uint04& child_idx) const;
335
337 {
338 return m_sorted_json_children;
339 }
340 bool hasNode(const String& child_node) const
341 {
342 return m_json_children.hasKey(child_node);
343 }
344
345 const String& nodeName() const
346 {
347 return m_name;
348 }
349
350 void remove(const String& child_node);
351 JSONNode& createChildNode(const String& child_node, NodeType type);
352 /**--------------------------------------------------------------------------------------------------
353 Fn: void JSONNode::operator=(const JSONNode& node)
354
355 A special case of the = operator for nodes. Note that this will not set the name of the node, but
356 set the contents equal to that of another
357
358 Author: Tyler Parke
359
360 Date: 2017-11-19
361 *-----------------------------------------------------------------------------------------------**/
363 {
364 m_value = node.m_value;
365 if (node.m_type == e_root)
366 m_type = e_node;//convert root to node
367 else
368 m_type = node.m_type;
369 for (const auto& iter : m_sorted_json_children)
370 {
371 delete iter;
372 }
373 m_sorted_json_children.clear();
374 m_json_children.clear();
375 for (const auto& iter : node.m_sorted_json_children)
376 {
377 m_sorted_json_children.add(new JSONNode(*iter));
378 if (!m_json_children.hasKey(iter->nodeName()))
379 m_json_children.add(iter->nodeName(), m_sorted_json_children.last());
380 }
381 return *this;
382 }
383
384
385 JSONNode& operator=(const String& value)
386 {
387 m_type = e_object;
388 m_value = value;
389 return *this;
390 }
391 template<class t_type>
393 {
394 m_type = e_object;
395 m_value = String(value.template as<DEGREES>());
396 return *this;
397 }
398
399 /**--------------------------------------------------------------------------------------------------
400 Fn: void JSONNode::operator=(const Time& node)
401
402 A special case Time equals. writes in YYYY/MM/DDTHH:mm:ss.fffZ format.
403
404 Author: Tyler Parke
405
406 Date: 2017-11-19
407 *-----------------------------------------------------------------------------------------------**/
408 JSONNode& operator=(const Time& time)
409 {
410 m_type = e_object;
411 m_value = time.toString(false, "YYYY/MM/DDTHH:mm:ss.fffZ");;
412 return *this;
413 }
414
415 template<class t_type, class t_allocator>
417 {
418 m_type = e_array;
419 m_value = String(buffer);
420 return *this;
421 }
422
423 template<uint01 t_dims, class t_type>
425 {
426 m_type = e_array;
427 m_value = String(buffer);
428 return *this;
429 }
430
431 /**--------------------------------------------------------------------------------------------------
432 Fn: bool JSONNode::isEmpty() const
433
434 Returns true if the node contains no information.
435
436 Author: Tyler Parke
437
438 Date: 2019-14-12
439 *-----------------------------------------------------------------------------------------------**/
440 [[nodiscard]] bool isEmpty() const
441 {
442 return m_value.size() == 0 && m_json_children.size() == 0;
443 }
444
445 /**--------------------------------------------------------------------------------------------------
446 Fn: void JSONNode::operator=(const t_type& node)
447
448 A general case t_type equals. Sets the value internal and predicts the type.
449
450 Author: Tyler Parke
451
452 Date: 2017-11-19
453 *-----------------------------------------------------------------------------------------------**/
454 template<class t_type>
455 JSONNode& operator=(const t_type& value)
456 {
458 m_type = e_number;
460 m_type = e_bool;
462 m_type = e_array;
463 else if (ObjectInfo<t_type>::Color)//An RGBColor is converted into an array of integers {red, green, blue, alpha}
464 m_type = e_array;
465 else
466 m_type = e_object;
467 m_value = String(value);
468 return *this;
469 }
470
471 /**--------------------------------------------------------------------------------------------------
472 Fn: void JSONNode::operator=()
473
474 Returns the number of children within this node.
475
476 Author: Tyler Parke
477
478 Date: 2017-11-19
479 *-----------------------------------------------------------------------------------------------**/
481 {
482 return cast<uint04>(m_json_children.size());
483 }
484 //Used for parsing our children in a for/each loop
485 [[nodiscard]] decltype(auto) begin()
486 {
487 return m_json_children.begin();
488 }
489 [[nodiscard]] decltype(auto) begin() const
490 {
491 return m_json_children.begin();
492 }
493
494 [[nodiscard]] decltype(auto) end()
495 {
496 return m_json_children.end();
497 }
498 [[nodiscard]] decltype(auto) end() const
499 {
500 return m_json_children.end();
501 }
502 static JSONNode ParseYAML(Scanner& scan);
503 protected:
504 /**--------------------------------------------------------------------------------------------------
505 Fn: JSONParser::parseJSON(Scanner& scan)
506
507 Reads in the next JSON item and adds it to this node's children
508
509 Parameters:
510 scan - The object tasked with reading in our data. Shold be just past the second '"' at the end of
511 the node's title at this point.
512
513 Author: Tyler Parke
514
515 Date: 2017-11-19
516
517 Returns: true if there is an adjacent child next to this one, false if end of stream or no additional
518 children.
519 *-----------------------------------------------------------------------------------------------**/
520 bool parseJSON(Scanner& scan);
521 bool parseJSONContent(char start, Scanner& scan);
522
523 /**--------------------------------------------------------------------------------------------------
524 Fn: JSONParser::parseYAML(Scanner& scan)
525
526 Reads in the next YAML item and adds it to this node's children
527
528 Parameters:
529 scan - The object tasked with reading in our data. Shold be just past the second '"' at the end of
530 the node's title at this point.
531
532 Author: Tyler Parke
533
534 Date: 2024-07-08
535
536 Returns: true if there is an adjacent child next to this one, false if end of stream or no additional
537 children.
538 *-----------------------------------------------------------------------------------------------**/
539 bool parseYAMLContent(uint04 indentention, Scanner& scan);
540
541 /**--------------------------------------------------------------------------------------------------
542 Fn: JSONParser::readChildrenNodes(Scanner& scan)
543
544 Reads in all of the children nodes for this node and adds them to the children list
545
546 Parameters:
547 scan - The object tasked with reading in our data. Shold be just before the first '"' specifying
548 the title
549
550 Author: Tyler Parke
551
552 Date: 2017-11-19
553 *-----------------------------------------------------------------------------------------------**/
554 void readChildrenNodes(Scanner& scan);
555
556 /**--------------------------------------------------------------------------------------------------
557 Fn: JSONParser::readData(Scanner& scan)
558
559 Reads in a single object type for this child.
560
561 Parameters:
562 scan - The object tasked with reading in our data. Shold be just past the first '"' specifying
563 the data
564
565 Author: Tyler Parke
566
567 Date: 2017-11-19
568 *-----------------------------------------------------------------------------------------------**/
569 void readData(Scanner& scan);
570
571 /**--------------------------------------------------------------------------------------------------
572 Fn: JSONParser::readArray(Scanner& scan)
573
574 Reads in an array of items for this child.
575
576 Parameters:
577 scan - The object tasked with reading in our data. Shold be just past the first '[' specifying
578 the beginning of the array
579
580 Author: Tyler Parke
581
582 Date: 2017-11-19
583 *-----------------------------------------------------------------------------------------------**/
584 void readArray(Scanner& scan);
585
586 /**--------------------------------------------------------------------------------------------------
587 Fn: JSONParser::WriteTabs(String& stream, uint04 tab_indention)
588
589 Writes tabs to the file
590
591 Parameters:
592 stream - Where to append the tabs
593 tab_indention - The number of tabs to write
594
595 Author: Tyler Parke
596
597 Date: 2017-11-19
598 *-----------------------------------------------------------------------------------------------**/
599 static void WriteTabs(String& stream, uint04 tab_indention);
600 static void ConvertToJSONString(String& string);
601 static void ConvertFromJSONString(String& string);
602 protected:
603 static TranslatedString UnexpectedCharErrorString(char current_char, const Scanner& scan);
604 static TranslatedString DuplicateChildErrorString(const String& child, const Scanner& scan);
605 static TranslatedString BadChildErrorString(const Scanner& scan);
606 protected:
608 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
609 const String m_name; //The name of the node
610 String m_value; //The value of the node
611 NodeType m_type;// the type of the node.
612 };
613
614}
615
616
#define NDEVR_BASE_API
Definition DLLInfo.h:78
#define lib_assert(expression, message)
Asserts some logic in the code. Disabled in non debug mode by default. Can be re-enabled in release u...
Definition LibAssert.h:70
Stores an angle in an optimized format.
Definition StringStream.h:352
The equivelent of std::vector but with a bit more control. The basic array unit of the library.
Definition Buffer.hpp:64
bool contains(const t_type &element) const
Definition Buffer.hpp:674
Definition Dictionary.h:48
Definition File.h:47
JavaScript Object Notation or JSON is an open - standard file format that uses human - readable text ...
Definition JSONParser.h:121
Buffer< JSONNode * > m_sorted_json_children
Definition JSONParser.h:607
JSONNode & operator=(const t_type &value)
Definition JSONParser.h:455
JSONNode & operator=(const String &value)
Definition JSONParser.h:385
JSONNode & operator=(const Buffer< t_type, t_allocator > &buffer)
Definition JSONParser.h:416
Dictionary< String, JSONNode * > m_json_children
Definition JSONParser.h:608
const String m_name
Definition JSONParser.h:609
JSONNode & operator=(const Time &time)
Definition JSONParser.h:408
decltype(auto) end()
Definition JSONParser.h:494
JSONNode & operator=(const JSONNode &node)
Definition JSONParser.h:362
String m_value
Definition JSONParser.h:610
decltype(auto) getAs() const
Definition JSONParser.h:286
uint04 size()
Definition JSONParser.h:480
JSONNode & operator=(const Vector< t_dims, t_type > &buffer)
Definition JSONParser.h:424
bool hasNode(const String &child_node) const
Definition JSONParser.h:340
decltype(auto) begin()
Definition JSONParser.h:485
const String & nodeName() const
Definition JSONParser.h:345
const JSONNode & get(const String &child_node) const
Definition JSONParser.h:303
NodeType
Definition JSONParser.h:125
decltype(auto) begin() const
Definition JSONParser.h:489
bool isEmpty() const
Definition JSONParser.h:440
JSONNode & operator=(const Angle< t_type > &value)
Definition JSONParser.h:392
NodeType m_type
Definition JSONParser.h:611
decltype(auto) end() const
Definition JSONParser.h:498
const Buffer< JSONNode * > & children() const
Definition JSONParser.h:336
static Angle< t_type > Convert(const String &value)
Definition JSONParser.h:59
static const String & Convert(const String &value)
Definition JSONParser.h:68
static Time Convert(const String &value)
Template specialization for time, as the format for time in JSON is not entirely specified,...
Definition JSONParser.h:85
Definition JSONParser.h:48
static t_type Convert(const String &value)
Definition JSONParser.h:50
Definition Scanner.h:41
Definition String.h:40
NDEVR_BASE_API String substr(uint04 start) const
Definition String.cpp:551
t_type getAs() const
Definition String.h:334
NDEVR_BASE_API uint04 indexOf(const String &sub_string, bool ignore_case=false, uint04 start_index=0) const
Definition String.cpp:208
Represents a timestamp with utilities for manipulation and conversion.
Definition Time.h:54
static constexpr uint08 SECOND
Definition Time.h:84
NDEVR_BASE_API String toString(bool get_local_time, const String &format_string) const
Converts the timestamp to a string representation. https://ndevr.org/time-patterns/.
Definition Time.cpp:115
Definition TranslatedString.h:9
An element of a vector space. An element of the real coordinate space Rn Basis vector,...
Definition Vector.hpp:62
Definition ACIColor.h:37
@ DEGREES
Definition Angle.h:66
uint64_t uint08
-Defines an alias representing an 8 byte, unsigned integer -Can represent exact integer values 0 thro...
Definition BaseValues.hpp:132
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
Definition BaseValues.hpp:120
constexpr bool isNaN(const t_type &value)
Query if 'value' is valid or invalid.
Definition BaseFunctions.hpp:200
double fltp08
Defines an alias representing an 8 byte floating-point number.
Definition BaseValues.hpp:181
Information about the object.
Definition ObjectInfo.h:56