@@ -29,6 +29,11 @@ auto doc = parser.iterate(json);
29
29
for (auto tweet : doc[" statuses" ]) {
30
30
std::string_view text = tweet[ "text"] ;
31
31
std::string_view screen_name = tweet[ "user"] [ "screen_name" ] ;
32
+ std::string_view screen_name;
33
+ {
34
+ ondemand::object user = tweet[ "user"] ;
35
+ screen_name = user[ "screen_name"] ;
36
+ }
32
37
uint64_t retweets = tweet[ "retweet_count"] ;
33
38
uint64_t favorites = tweet[ "favorite_count"] ;
34
39
cout << screen_name << " (" << retweets << " retweets / " << favorites << " favorites): " << text << endl;
@@ -313,6 +318,11 @@ To help visualize the algorithm, we'll walk through the example C++ given at the
313
318
rely on error chaining, so it is possible to delay error checks: we shall shortly explain error
314
319
chaining more fully.
315
320
321
+ NOTE: You should always have such a ` document ` instance (here ` doc ` ) and it should remain in scope for the duration
322
+ of your parsing function. E.g., you should not use the returned document as a temporary (e.g., ` auto x = parser.iterate(json).get_object(); ` )
323
+ followed by other operations as the destruction of the ` document ` instance makes all of the derived instances
324
+ ill-defined.
325
+
316
326
317
327
3 . We iterate over the "statuses" field using a typical C++ iterator, reading past the initial
318
328
` { "statuses": [ { ` .
@@ -355,6 +365,11 @@ To help visualize the algorithm, we'll walk through the example C++ given at the
355
365
when you attempt to cast the final ` simdjson_result<object> ` to object. Upon casting, an exception is
356
366
thrown if there was an error.
357
367
368
+ NOTE: while the document can be queried once for a key as if it were an object, it is not an actual object
369
+ instance. If you need to treat it as an object (e.g., to query more than one keys), you can cast it as
370
+ such ` ondemand::object root_object = doc.get_object(); ` .
371
+
372
+
358
373
4 . We get the ` "text" ` field as a string.
359
374
360
375
``` c++
@@ -379,20 +394,28 @@ To help visualize the algorithm, we'll walk through the example C++ given at the
379
394
4 . We get the ` "screen_name" ` from the ` "user" ` object.
380
395
381
396
``` c++
382
- std::string_view screen_name = tweet[" user" ][" screen_name" ];
397
+ ondemand::object user = tweet[" user" ];
398
+ screen_name = user[" screen_name" ];
383
399
```
384
400
385
401
First, ` ["user"] ` checks whether there are any more object fields by looking for either ` , ` or
386
402
` } ` . Then it matches ` "user" ` and validates the ` : ` .
387
403
388
404
` ["screen_name"] ` then converts to object, checking for ` { ` , and finds ` "screen_name" ` .
389
405
390
- To convert to string, ` lemire ` is written to the document's string buffer, which now has * two *
391
- string_views pointing into it, and looks like ` first!\0lemire\0 ` .
406
+ To convert the result to usable string (i.e., the screen name ` lemire ` ), the characters are written to the document's
407
+ string buffer (after possibly escaping them), which now has * two * string_views pointing into it, and looks like ` first!\0lemire\0 ` .
392
408
393
409
Finally, the temporary user object is destroyed, causing it to skip the remainder of the object
394
410
(` } ` ).
395
411
412
+ NOTE: You may only have one active array or object active at any given time. An array or an object becomes
413
+ active when the ` ondemand::object ` or ` ondemand::array ` is created, and it releases its 'focus' when
414
+ its destructor is called. If you create an array or an object located inside a parent object or array,
415
+ the child array or object becomes active while the parent becomes temporarily inactive. If you access
416
+ several sibling objects or arrays, you must ensure that the destructor is called by scoping each access
417
+ (see Iteration Safety section below for further details).
418
+
396
419
5 . We get ` "retweet_count" ` and ` "favorite_count" ` as unsigned integers.
397
420
398
421
``` c++
@@ -484,8 +507,6 @@ for(auto field : doc.get_object()) {
484
507
}
485
508
```
486
509
487
-
488
-
489
510
### Iteration Safety
490
511
491
512
The On Demand API is powerful. To compensate, we add some safeguards to ensure that it can be used without fear
@@ -501,6 +522,48 @@ in production systems:
501
522
if it was ` nullptr ` but did not care what the actual value was--it will iterate. The destructor automates
502
523
the iteration.
503
524
525
+ Some care is needed when using the On Demand API in scenarios where you need to access several sibling arrays or objects because
526
+ only one object or array can be active at any one time. Let us consider the following example:
527
+
528
+ ``` C++
529
+ ondemand::parser parser;
530
+ const padded_string json = R"( { "parent": {"child1": {"name": "John"} , "child2": {"name": "Daniel"}} })" _padded;
531
+ auto doc = parser.iterate(json);
532
+ ondemand::object parent = doc[" parent" ];
533
+ // parent owns the focus
534
+ ondemand::object c1 = parent[" child1" ];
535
+ // c1 owns the focus
536
+ //
537
+ if (std::string_view(c1[" name" ]) != " John" ) { ... }
538
+ // c2 attempts to grab the focus from parent but fails
539
+ ondemand::object c2 = parent[ "child2"] ;
540
+ // c2 is now in an unsafe state and the following line would be unsafe
541
+ // if(std::string_view(c2[ "name"] ) != "Daniel") { return false; }
542
+ ```
543
+
544
+ A correct usage is given by the following example:
545
+
546
+ ```C++
547
+ ondemand::parser parser;
548
+ const padded_string json = R"({ "parent": {"child1": {"name": "John"} , "child2": {"name": "Daniel"}} })"_padded;
549
+ auto doc = parser.iterate(json);
550
+ ondemand::object parent = doc["parent"];
551
+ // At this point, parent owns the focus
552
+ {
553
+ ondemand::object c1 = parent["child1"];
554
+ // c1 grabbed the focus from parent
555
+ if(std::string_view(c1["name"]) != "John") { return false; }
556
+ }
557
+ // c1 went out of scope, so its destructor was called and the focus
558
+ // was handed back to parent.
559
+ {
560
+ ondemand::object c2 = parent["child2"];
561
+ // c2 grabbed the focus from parent
562
+ // the following is safe:
563
+ if(std::string_view(c2["name"]) != "Daniel") { return false; }
564
+ }
565
+ ```
566
+
504
567
### Benefits of the On Demand Approach
505
568
506
569
We expect that the On Demand approach has many of the performance benefits of the schema-based approach, while providing a flexibility that is similar to that of the DOM-based approach.
0 commit comments