1 /*******************************************************************************
2 
3     Copyright:
4         Copyright (C) 2008 Aaron Craelius & Kris Bell
5         Some parts copyright (c) 2009-2016 dunnhumby Germany GmbH.
6         All rights reserved.
7 
8     License:
9         Tango Dual License: 3-Clause BSD License / Academic Free License v3.0.
10         See LICENSE_TANGO.txt for details.
11 
12     Version: July 2008: Initial release
13 
14     Authors: Aaron, Kris
15 
16  *******************************************************************************/
17 
18 module ocean.text.json.Json;
19 
20 import ocean.meta.types.Qualifiers;
21 
22 import core.stdc.stdarg;
23 
24 import ocean.core.Verify;
25 
26 import ocean.io.model.IConduit;
27 
28 import ocean.text.json.JsonEscape;
29 
30 import ocean.text.json.JsonParser;
31 
32 import Float = ocean.text.convert.Float;
33 
34 version (unittest) import ocean.core.Test;
35 
36 ///
37 unittest
38 {
39 
40     // Typical usage is as follows:
41 
42     auto json = new Json!(char);
43     json.parse(`{"t": true, "n":null, "array":["world", [4, 5]]}`);
44 
45 
46     // Convert back to text format:
47 
48     test!("==")(json.value.print(),
49         `{"t":true,"n":null,"array":["world", [4, 5]]}`);
50 
51 
52     // Constructing json within your code leverages a handful of factories
53     // within a document instance. This example creates a document from an
54     // array of values:
55 
56     with (json)
57         value = array (true, false, null, "text");
58     test!("==")(json.value.print(), `[true, false, null, "text"]`);
59 
60 
61     // Setting the document to contain a simple object instead:
62 
63     with (json)
64         value = object (pair("a", value(10)));
65     test!("==")(json.value.print(), `{"a":10}`);
66 
67 
68     // Objects may be constructed with multiple attribute pairs like so:
69 
70     with (json)
71         value = object (pair("a", value(10)), pair("b", value(true)));
72     test!("==")(json.value.print(), `{"a":10,"b":true}`);
73 
74 
75     // Substitute arrays, or other objects as values where appropriate:
76 
77     with (json)
78         value = object (pair("a", array(10, true, object(pair("b")))));
79     test!("==")(json.value.print(), `{"a":[10, true, {"b":null}]}`);
80 }
81 
82 
83 /*******************************************************************************
84 
85     Parse json text into a set of inter-related structures.
86 
87  *******************************************************************************/
88 
89 class Json(T) : JsonParser!(T)
90 {
91     /// use these types for external references
92     public alias JsonValue*  Value;
93     public alias NameValue*  Attribute;
94     public alias JsonObject* Composite;
95 
96     /// enumerates the seven acceptable JSON value types
97     public enum Type {Null, String, RawString, Number, Object, Array, True, False};
98 
99     private Value root;
100 
101     /***********************************************************************
102 
103       Construct a json instance, with a default value of null
104 
105      ***********************************************************************/
106 
107     this ()
108     {
109         arrays.length = 16;
110         parse (null);
111     }
112 
113     /***********************************************************************
114 
115       Parse the given text and return a resultant Value type. Also
116       sets the document value.
117 
118      ***********************************************************************/
119 
120     final Value parse (const(T)[] json)
121     {
122         nesting = 0;
123         attrib.reset;
124         values.reset;
125         objects.reset;
126         foreach (ref p; arrays)
127             p.index = 0;
128 
129         root = createValue;
130         if (super.reset (json))
131         {
132             if (curType is Token.BeginObject)
133                 root.set (parseObject);
134             else
135             {
136                 if (curType is Token.BeginArray)
137                     root.set (parseArray);
138                 else
139                     exception ("invalid json document");
140             }
141         }
142 
143         return root;
144     }
145 
146     /***********************************************************************
147 
148       Return a text representation of this document
149 
150      ***********************************************************************/
151 
152     final const(T)[] toString (const(T)[] space=null, int decimals=2)
153     {
154         return root.print (space, decimals);
155     }
156 
157     /***********************************************************************
158 
159       Returns the root value of this document
160 
161      ***********************************************************************/
162 
163     final Value value ()
164     {
165         return root;
166     }
167 
168     /***********************************************************************
169 
170       Set the root value of this document
171 
172      ***********************************************************************/
173 
174     final Value value (Value v)
175     {
176         return root = v;
177     }
178 
179     /***********************************************************************
180 
181       Create a text value
182 
183      ***********************************************************************/
184 
185     final Value value (const(T)[] v)
186     {
187         return createValue.set (v);
188     }
189 
190     /***********************************************************************
191 
192       Create a boolean value
193 
194      ***********************************************************************/
195 
196     final Value value (bool v)
197     {
198         return createValue.set (v);
199     }
200 
201     /***********************************************************************
202 
203       Create a numeric value
204 
205      ***********************************************************************/
206 
207     final Value value (double v)
208     {
209         return createValue.set (v);
210     }
211 
212     /***********************************************************************
213 
214       Create a single Value from an array of Values
215 
216      ***********************************************************************/
217 
218     final Value value (Value[] vals)
219     {
220         return createValue.set (vals);
221     }
222 
223     /***********************************************************************
224 
225       Create an array of values
226 
227      ***********************************************************************/
228 
229     final Value array (...)
230     {
231         return createValue.set (this, _arguments, _argptr);
232     }
233 
234     /***********************************************************************
235 
236       Create an attribute/value pair, where value defaults to
237       null
238 
239      ***********************************************************************/
240 
241     Attribute pair (const(T)[] name, Value value = null)
242     {
243         if (value is null)
244             value = createValue;
245         return createAttribute.set (name, value);
246     }
247 
248     /***********************************************************************
249 
250       Create a composite from zero or more pairs, and return as
251       a value
252 
253      ***********************************************************************/
254 
255     final Value object (Attribute[] set...)
256     {
257         return createValue.set (createObject.add (set));
258     }
259 
260     /***********************************************************************
261 
262       Internal factory to create values
263 
264      ***********************************************************************/
265 
266     private Value createValue ()
267     {
268         return values.allocate.reset;
269     }
270 
271     /***********************************************************************
272 
273       Internal factory to create composites
274 
275      ***********************************************************************/
276 
277     private Composite createObject ()
278     {
279         return objects.allocate.reset;
280     }
281 
282     /***********************************************************************
283 
284       Internal factory to create attributes
285 
286      ***********************************************************************/
287 
288     private Attribute createAttribute ()
289     {
290         return attrib.allocate;
291     }
292 
293     /***********************************************************************
294 
295       Throw a generic exception
296 
297      ***********************************************************************/
298 
299     private void exception (istring msg)
300     {
301         throw new Exception (msg);
302     }
303 
304     /***********************************************************************
305 
306       Parse an instance of a value
307 
308      ***********************************************************************/
309 
310     private Value parseValue ()
311     {
312         auto v = values.allocate;
313 
314         switch (super.curType)
315         {
316             case Token.True:
317                 v.set (Type.True);
318                 break;
319 
320             case Token.False:
321                 v.set (Type.False);
322                 break;
323 
324             case Token.Null:
325                 v.set (Type.Null);
326                 break;
327 
328             case Token.BeginObject:
329                 v.set (parseObject);
330                 break;
331 
332             case Token.BeginArray:
333                 v.set (parseArray);
334                 break;
335 
336             case Token.String:
337                 v.set (super.value, true);
338                 break;
339 
340             case Token.NaN:
341                 v.set (Float.parse ("NaN"));
342                 break;
343 
344             case Token.Infinity:
345                 v.set (Float.parse ("Infinity"));
346                 break;
347 
348             case Token.NegInfinity:
349                 v.set (Float.parse ("-Infinity"));
350                 break;
351 
352             case Token.Number:
353                 v.set (Float.parse (super.value));
354                 break;
355 
356             default:
357                 v.set (Type.Null);
358                 break;
359         }
360 
361         return v;
362     }
363 
364     /***********************************************************************
365 
366       Parse an object declaration
367 
368      ***********************************************************************/
369 
370     private Composite parseObject ()
371     {
372         auto o = objects.allocate.reset;
373 
374         while (super.next)
375         {
376             if (super.curType is Token.EndObject)
377                 return o;
378 
379             if (super.curType != Token.Name)
380                 super.expected ("an attribute-name", super.str.ptr);
381 
382             auto name = super.value;
383 
384             if (! super.next)
385                 super.expected ("an attribute-value", super.str.ptr);
386 
387             o.append (attrib.allocate.set (name, parseValue));
388         }
389 
390         return o;
391     }
392 
393     /***********************************************************************
394 
395       Parse an array declaration
396 
397      ***********************************************************************/
398 
399     private Value[] parseArray ()
400     {
401         if (nesting >= arrays.length)
402             exception ("array nesting too deep within document");
403 
404         auto array = &arrays[nesting++];
405         auto start = array.index;
406 
407         while (super.next && super.curType != Token.EndArray)
408         {
409             if (array.index >= array.content.length)
410                 array.content.length = array.content.length + 300;
411 
412             array.content [array.index++] = parseValue;
413         }
414 
415         if (super.curType != Token.EndArray)
416             exception ("malformed array");
417 
418         --nesting;
419         return array.content [start .. array.index];
420     }
421 
422     /***********************************************************************
423 
424       Represents an attribute/value pair. Aliased as Attribute
425 
426      ***********************************************************************/
427 
428     struct NameValue
429     {
430         private Attribute       next;
431         public  const(T)[]     name;
432         public  Value           value;
433 
434         /***************************************************************
435 
436           Set a name and a value for this attribute
437 
438           Returns itself, for use with Composite.add()
439 
440          ***************************************************************/
441 
442         Attribute set (const(T)[] key, Value val)
443         {
444             name = key;
445             value = val;
446             return &this;
447         }
448     }
449 
450     /***********************************************************************
451 
452       Represents a single json Object (a composite of named
453       attribute/value pairs).
454 
455       This is aliased as Composite
456 
457      ***********************************************************************/
458 
459     struct JsonObject
460     {
461         private Attribute head,
462                 tail;
463 
464         /***************************************************************
465 
466          ***************************************************************/
467 
468         Composite reset ()
469         {
470             head = tail = null;
471             return &this;
472         }
473 
474         /***************************************************************
475 
476           Append an attribute/value pair
477 
478          ***************************************************************/
479 
480         Composite append (Attribute a)
481         {
482             if (tail)
483                 tail.next = a, tail = a;
484             else
485                 head = tail = a;
486             return &this;
487         }
488 
489         /***************************************************************
490 
491           Add a set of attribute/value pairs
492 
493          ***************************************************************/
494 
495         Composite add (Attribute[] set...)
496         {
497             foreach (attr; set)
498                 append (attr);
499             return &this;
500         }
501 
502         /***************************************************************
503 
504           Construct and return a hashmap of Object attributes.
505           This will be a fairly costly operation, so consider
506           alternatives where appropriate
507 
508          ***************************************************************/
509 
510         Value[immutable(T)[]] hashmap ()
511         {
512             Value[immutable(T)[]] members;
513 
514             auto a = head;
515             while (a)
516             {
517                 members[idup(a.name)] = a.value;
518                 a = a.next;
519             }
520 
521             return members;
522         }
523 
524         /***************************************************************
525 
526           Return a corresponding value for the given attribute
527           name. Does a linear lookup across the attribute set
528 
529          ***************************************************************/
530 
531         Value value (const(T)[] name)
532         {
533             auto a = head;
534             while (a)
535                 if (name == a.name)
536                     return a.value;
537                 else
538                     a = a.next;
539 
540             return null;
541         }
542 
543         /***************************************************************
544 
545           Iterate over our attribute names and values
546 
547          ***************************************************************/
548 
549         Iterator attributes ()
550         {
551             Iterator i = {head};
552             return i;
553         }
554 
555         /***************************************************************
556 
557           Iterate over our attribute names. Note that we
558           use a Fruct to handle this, since foreach does
559           not operate cleanly with pointers (it doesn't
560           automatically dereference them), whereas using
561           x.attributes() does.
562 
563           We may also use this to do some name filtering
564 
565          ***************************************************************/
566 
567         static struct Iterator
568         {
569             private Attribute head;
570 
571             int opApply (scope int delegate(ref const(T)[] key, ref Value val) dg)
572             {
573                 int res;
574 
575                 auto a = head;
576                 while (a)
577                 {
578                     if ((res = dg (a.name, a.value)) != 0)
579                         break;
580                     a = a.next;
581                 }
582                 return res;
583             }
584         }
585     }
586 
587     /***********************************************************************
588 
589       Represents a json value that is one of the seven types
590       specified via the Json.Type enum
591 
592      ***********************************************************************/
593 
594     struct JsonValue
595     {
596         private union
597         {
598             Value[]         array;
599             real            number;
600             const(T)[]     string;
601             Composite       object;
602         }
603 
604         public Type type;               /// the type of this node
605         alias reset set;                /// alternate name for reset
606 
607         /***************************************************************
608 
609           return true if this node is of the given type
610 
611          ***************************************************************/
612 
613         equals_t opEquals (Type t)
614         {
615             return type is t;
616         }
617 
618         /***************************************************************
619 
620           explicitly provide same opEquals as auto-generated one to
621           avoid deprecation warning being printed (compiler can't know
622           if previous one was intentional or a typo)
623 
624         ***************************************************************/
625 
626         equals_t opEquals (JsonValue rhs)
627         {
628             return this is rhs;
629         }
630 
631         /***************************************************************
632 
633           Return true if this value represent True
634 
635          ***************************************************************/
636 
637         bool toBool ()
638         {
639             return (type is Type.True);
640         }
641 
642         /***************************************************************
643 
644           Return the string content. Returns null if this
645           value is not a string.
646 
647           Uses dst for escape conversion where possible.
648 
649          ***************************************************************/
650 
651         const(T)[] toString (T[] dst = null)
652         {
653             if (type is Type.RawString)
654                 return string;
655 
656             if (type is Type.String)
657                 return unescape (string, dst);
658 
659             return null;
660         }
661 
662         /***************************************************************
663 
664           Emit the string content to the given delegate, with
665           escape conversion as required.
666 
667           Returns false if this is not a String value
668 
669          ***************************************************************/
670 
671         bool toString (scope void delegate(const(T)[]) dg)
672         {
673             if (type is Type.RawString)
674                 dg(string);
675             else
676                 if (type is Type.String)
677                     unescape (string, dg);
678                 else
679                     return false;
680             return true;
681         }
682 
683         /***************************************************************
684 
685           Return the content as a Composite/Object. Returns null
686           if this value is not a Composite.
687 
688          ***************************************************************/
689 
690         Composite toObject ()
691         {
692             return type is Type.Object ? object : null;
693         }
694 
695         /***************************************************************
696 
697           Return the content as a double. Returns nan where
698           the value is not numeric.
699 
700          ***************************************************************/
701 
702         real toNumber ()
703         {
704             return type is Type.Number ? number : real.nan;
705         }
706 
707         /***************************************************************
708 
709           Return the content as an array. Returns null where
710           the value is not an array.
711 
712          ***************************************************************/
713 
714         Value[] toArray ()
715         {
716             return (type is Type.Array) ? array : null;
717         }
718 
719         /***************************************************************
720 
721           Set this value to represent a string. If 'escaped'
722           is set, the string is assumed to have pre-converted
723           escaping of reserved characters (such as \t).
724 
725          ***************************************************************/
726 
727         Value set (const(T)[] str, bool escaped = false)
728         {
729             type = escaped ? Type.String : Type.RawString;
730             string = str;
731             return &this;
732         }
733 
734         /***************************************************************
735 
736           Set this value to represent an object.
737 
738          ***************************************************************/
739 
740         Value set (Composite obj)
741         {
742             type = Type.Object;
743             object = obj;
744             return &this;
745         }
746 
747         /***************************************************************
748 
749           Set this value to represent a number.
750 
751          ***************************************************************/
752 
753         Value set (real num)
754         {
755             type = Type.Number;
756             number = num;
757             return &this;
758         }
759 
760         /***************************************************************
761 
762           Set this value to represent a boolean.
763 
764          ***************************************************************/
765 
766         Value set (bool b)
767         {
768             type = b ? Type.True : Type.False;
769             return &this;
770         }
771 
772         /***************************************************************
773 
774           Set this value to represent an array of values.
775 
776          ***************************************************************/
777 
778         Value set (Value[] a)
779         {
780             type = Type.Array;
781             array = a;
782             return &this;
783         }
784 
785         /***************************************************************
786 
787           Set this value to represent null
788 
789          ***************************************************************/
790 
791         Value reset ()
792         {
793             type = Type.Null;
794             return &this;
795         }
796 
797         /***************************************************************
798 
799           Return a text representation of this value
800 
801          ***************************************************************/
802 
803         const(T)[] print (const(T)[] space=null, int decimals=2)
804         {
805             T[] tmp;
806             void append (const(T)[] s) { tmp ~= s; }
807             print (&append, space, decimals);
808             return tmp;
809         }
810 
811         /***************************************************************
812 
813           Emit a text representation of this value to the
814           given OutputStream
815 
816          ***************************************************************/
817 
818         Value print (OutputStream s, const(T)[] space=null, int decimals=2)
819         {
820             return print ((const(T)[] t){s.write(t);}, space, decimals);
821         }
822 
823         /***************************************************************
824 
825           Emit a text representation of this value to the
826           provided delegate
827 
828          ***************************************************************/
829 
830         Value print (scope void delegate(const(T)[]) append, const(T)[] space=null, int decimals=2)
831         {
832             auto indent = 0;
833 
834             void newline ()
835             {
836                 if (space.length)
837                 {
838                     append ("\n");
839                     for (auto i=0; i < indent; i++)
840                         append (space);
841                 }
842             }
843 
844             void printValue (Value val)
845             {
846                 void printObject (Composite obj)
847                 {
848                     if (obj is null)
849                         return;
850 
851                     bool first = true;
852                     append ("{");
853                     indent++;
854 
855                     foreach (k, v; obj.attributes)
856                     {
857                         if (!first)
858                             append (",");
859                         newline;
860                         append (`"`), append(k), append(`":`);
861                         printValue (v);
862                         first = false;
863                     }
864                     indent--;
865                     newline;
866                     append ("}");
867                 }
868 
869                 void printArray (Value[] arr)
870                 {
871                     bool first = true;
872                     append ("[");
873                     indent++;
874                     foreach (v; arr)
875                     {
876                         if (!first)
877                             append (", ");
878                         newline;
879                         printValue (v);
880                         first = false;
881                     }
882                     indent--;
883                     newline;
884                     append ("]");
885                 }
886 
887 
888                 if (val is null)
889                     return;
890 
891                 T[64] tmp = void;
892 
893                 switch (val.type)
894                 {
895                     case Type.String:
896                     append (`"`), append(val..string), append(`"`);
897                     break;
898 
899                     case Type.RawString:
900                     append (`"`), escape(val..string, append), append(`"`);
901                     break;
902 
903                     case Type.Number:
904                     append (Float.format (tmp, val.toNumber, decimals));
905                     break;
906 
907                     case Type.Object:
908                     auto obj = val.toObject;
909                     verify(obj !is null);
910                     printObject (val.toObject);
911                     break;
912 
913                     case Type.Array:
914                     printArray (val.toArray);
915                     break;
916 
917                     case Type.True:
918                     append ("true");
919                     break;
920 
921                     case Type.False:
922                     append ("false");
923                     break;
924 
925                     default:
926                     case Type.Null:
927                     append ("null");
928                     break;
929                 }
930             }
931 
932             printValue(&this);
933             return &this;
934         }
935 
936         /***************************************************************
937 
938           Set to a specified type
939 
940          ***************************************************************/
941 
942         private Value set (Type type)
943         {
944             this.type = type;
945             return &this;
946         }
947 
948         /***************************************************************
949 
950           Set a variety of values into an array type
951 
952          ***************************************************************/
953 
954         private Value set (Json host, TypeInfo[] info, va_list args)
955         {
956             Value[] list;
957 
958             foreach (type; info)
959             {
960                 Value v;
961                 if (type is typeid(Value))
962                     v = va_arg!(Value)(args);
963                 else
964                 {
965                     v = host.createValue;
966                     if (type is typeid(double))
967                         v.set (va_arg!(double)(args));
968                     else
969                     if (type is typeid(int))
970                         v.set (va_arg!(int)(args));
971                     else
972                     if (type is typeid(bool))
973                         v.set (va_arg!(bool)(args));
974                     else
975                     if (type is typeid(long))
976                         v.set (va_arg!(long)(args));
977                     else
978                     if (type is typeid(Composite))
979                         v.set (va_arg!(Composite)(args));
980                     else
981                     if (type is typeid(istring))
982                         v.set (va_arg!(T[])(args));
983                     else
984                     if (type is typeid(void*))
985                         va_arg!(void*)(args);
986                     else
987                     if (type is typeid(null))
988                         va_arg!(void*)(args);
989                     else
990                     {
991                         host.exception ("JsonValue.set :: unexpected type: "~type.toString);
992                     }
993                 }
994                 list ~= v;
995             }
996             return set (list);
997         }
998     }
999 
1000     /***********************************************************************
1001 
1002       Internal allocation mechanism
1003 
1004      ***********************************************************************/
1005 
1006     private struct Allocator(T)
1007     {
1008         private T[]     list;
1009         private T[][]   lists;
1010         private int     index,
1011                 block;
1012 
1013         void reset ()
1014         {
1015             // discard since prior lists are not initialized
1016             lists.length = 0;
1017             assumeSafeAppend(lists);
1018             block = -1;
1019             newlist;
1020         }
1021 
1022         T* allocate ()
1023         {
1024             if (index >= list.length)
1025                 newlist;
1026 
1027             auto p = &list [index++];
1028             return p;
1029         }
1030 
1031         private void newlist ()
1032         {
1033             index = 0;
1034             if (++block >= lists.length)
1035             {
1036                 lists.length = lists.length + 1;
1037                 assumeSafeAppend(lists);
1038                 lists[$-1] = new T[256];
1039             }
1040             list = lists [block];
1041         }
1042     }
1043 
1044     /***********************************************************************
1045 
1046       Internal use for parsing array values
1047 
1048      ***********************************************************************/
1049 
1050     private struct Array
1051     {
1052         uint            index;
1053         Value[]         content;
1054     }
1055 
1056     /***********************************************************************
1057 
1058       Internal document representation
1059 
1060      ***********************************************************************/
1061 
1062     private alias Allocator!(NameValue)     Attrib;
1063     private alias Allocator!(JsonValue)     Values;
1064     private alias Allocator!(JsonObject)    Objects;
1065 
1066     private Attrib                          attrib;
1067     private Values                          values;
1068     private Array[]                         arrays;
1069     private Objects                         objects;
1070     private uint                            nesting;
1071 }
1072 
1073 
1074 
1075 /*******************************************************************************
1076 
1077  *******************************************************************************/
1078 
1079 unittest
1080 {
1081     with (new Json!(char))
1082     {
1083         root = object
1084             (
1085              pair ("edgar", value("friendly")),
1086              pair ("count", value(11.5)),
1087              pair ("array", value(array(1, 2)))
1088             );
1089 
1090         auto value = toString();
1091         test (value == `{"edgar":"friendly","count":11.5,"array":[1, 2]}`, value);
1092     }
1093 }
1094 
1095 unittest
1096 {
1097     // check with a separator of the tab character
1098     with (new Json!(char))
1099     {
1100         root = object
1101             (
1102              pair ("edgar", value("friendly")),
1103              pair ("count", value(11.5)),
1104              pair ("array", value(array(1, 2)))
1105             );
1106 
1107         auto value = toString ("\t");
1108         test (value == "{\n\t\"edgar\":\"friendly\",\n\t\"count\":11.5,\n\t\"array\":[\n\t\t1, \n\t\t2\n\t]\n}", value);
1109     }
1110 }
1111 
1112 unittest
1113 {
1114     // check with a separator of five spaces
1115     with (new Json!(char))
1116     {
1117         root = object
1118             (
1119              pair ("edgar", value("friendly")),
1120              pair ("count", value(11.5)),
1121              pair ("array", value(array(1, 2)))
1122             );
1123 
1124         auto value = toString ("     ");
1125         test (value == "{\n     \"edgar\":\"friendly\",\n     \"count\":11.5,\n     \"array\":[\n          1, \n          2\n     ]\n}");
1126     }
1127 }
1128 
1129 unittest
1130 {
1131     auto p = new Json!(char);
1132     auto arr = p.array(null);
1133 }
1134 
1135 unittest
1136 {
1137     auto p = new Json!(char);
1138     auto v = p.parse (`{"t": true, "f":false, "n":null, "hi":["world", "big", 123, [4, 5, ["foo"]]]}`);
1139     with (p)
1140         value = object(pair("a", array(null, true, false, 30, object(pair("foo")))), pair("b", value(10)));
1141 
1142     p.parse ("[-1]");
1143     p.parse ("[11.23477]");
1144     p.parse(`["foo"]`);
1145     p.parse(`{"foo": {"ff" : "ffff"}`);
1146 
1147     with (new Json!(char))
1148     {
1149         root = object(pair("array", array(null)));
1150     }
1151 }