1 ## oils_failures_allowed: 1
2 ## tags: dev-minimal
3
4 #### usage errors
5
6 json read zz
7 echo status=$?
8
9 json write
10
11 ## status: 3
12 ## STDOUT:
13 status=2
14 ## END
15
16 #### json write STRING
17 shopt --set parse_proc
18
19 json write ('foo')
20 var s = 'foo'
21 json write (s)
22 ## STDOUT:
23 "foo"
24 "foo"
25 ## END
26
27 #### json write ARRAY
28 json write (:|foo.cc foo.h|)
29 json write (['foo.cc', 'foo.h'], space=0)
30 ## STDOUT:
31 [
32 "foo.cc",
33 "foo.h"
34 ]
35 ["foo.cc","foo.h"]
36 ## END
37
38 #### json write Dict
39 json write ({k: 'v', k2: [4, 5]})
40
41 json write ([{k: 'v', k2: 'v2'}, {}])
42
43 ## STDOUT:
44 {
45 "k": "v",
46 "k2": [
47 4,
48 5
49 ]
50 }
51 [
52 {
53 "k": "v",
54 "k2": "v2"
55 },
56 {}
57 ]
58 ## END
59
60 #### json write space=0, space=4
61 shopt --set parse_proc
62
63 var mydict = {name: "bob", age: 30}
64
65 json write (mydict, space=0)
66 json write (mydict, space=4)
67 ## STDOUT:
68 {"name":"bob","age":30}
69 {
70 "name": "bob",
71 "age": 30
72 }
73 ## END
74
75 #### json write in command sub
76 shopt -s oil:all # for echo
77 var mydict = {name: "bob", age: 30}
78 json write (mydict)
79 var x = $(json write (mydict))
80 echo $x
81 ## STDOUT:
82 {
83 "name": "bob",
84 "age": 30
85 }
86 {
87 "name": "bob",
88 "age": 30
89 }
90 ## END
91
92 #### json read passed invalid args
93
94 # EOF
95 json read
96 echo status=$?
97
98 json read 'z z'
99 echo status=$?
100
101 json read a b c
102 echo status=$?
103
104 ## STDOUT:
105 status=1
106 status=2
107 status=2
108 ## END
109
110 #### json read uses $_reply var
111
112 # space before true
113 echo ' true' | json read
114 json write (_reply)
115
116 ## STDOUT:
117 true
118 ## END
119
120 #### json read then json write
121
122 # BUG with space before true
123 echo '{"name": "bob", "age": 42, "ok": true}' | json read
124 json write (_reply)
125
126 echo '{"name": "bob", "age": 42, "ok":true}' | json read
127 json write (_reply)
128
129 echo '{"name": {}, "age": {}, "x":-1, "y": -0}' | json read
130 json write (_reply)
131
132 ## STDOUT:
133 {
134 "name": "bob",
135 "age": 42,
136 "ok": true
137 }
138 {
139 "name": "bob",
140 "age": 42,
141 "ok": true
142 }
143 {
144 "name": {},
145 "age": {},
146 "x": -1,
147 "y": 0
148 }
149 ## END
150
151 #### json read with redirect
152 echo '{"age": 42}' > $TMP/foo.txt
153 json read (&x) < $TMP/foo.txt
154 pp cell_ x
155 ## STDOUT:
156 x = (Cell exported:F readonly:F nameref:F val:(value.Dict d:[Dict age (value.Int i:42)]))
157 ## END
158
159 #### json read at end of pipeline (relies on lastpipe)
160 echo '{"age": 43}' | json read (&y)
161 pp cell_ y
162 ## STDOUT:
163 y = (Cell exported:F readonly:F nameref:F val:(value.Dict d:[Dict age (value.Int i:43)]))
164 ## END
165
166 #### invalid JSON
167 echo '{' | json read (&y)
168 echo pipeline status = $?
169 pp test_ (y)
170 ## status: 1
171 ## STDOUT:
172 pipeline status = 1
173 ## END
174
175 #### Extra data after valid JSON
176
177 # Trailing space is OK
178 echo '42 ' | json read
179 echo num space $?
180
181 echo '{} ' | json read
182 echo obj space $?
183
184 echo '42 # comment' | json8 read
185 echo num comment $?
186
187 echo '{} # comment ' | json8 read
188 echo obj comment $?
189
190 echo '42]' | json read
191 echo num bracket $?
192
193 echo '{}]' | json read
194 echo obj bracket $?
195
196 ## STDOUT:
197 num space 0
198 obj space 0
199 num comment 0
200 obj comment 0
201 num bracket 1
202 obj bracket 1
203 ## END
204
205 #### json write expression
206 json write ([1,2,3], space=0)
207 echo status=$?
208
209 json write (5, 6) # to many args
210 echo status=$?
211
212 ## status: 3
213 ## STDOUT:
214 [1,2,3]
215 status=0
216 ## END
217
218 #### json write evaluation error
219
220 #var block = ^(echo hi)
221 #json write (block)
222 #echo status=$?
223
224 # undefined var
225 json write (a)
226 echo 'should have failed'
227
228 ## status: 1
229 ## STDOUT:
230 ## END
231
232 #### json write of List in cycle
233
234 var L = [1, 2, 3]
235 setvar L[0] = L
236 pp test_ (L)
237
238 json write (L)
239 echo status=$?
240
241 ## status: 0
242 ## STDOUT:
243 (List) [[...],2,3]
244 status=1
245 ## END
246
247 #### json write of Dict in cycle
248
249 var d = {}
250 setvar d.k = d
251
252 pp test_ (d)
253
254 json write (d)
255 echo status=$?
256
257 ## STDOUT:
258 (Dict) {"k":{...}}
259 status=1
260 ## END
261
262 #### json write of List/Dict referenced twice (bug fix)
263
264 var mylist = [1,2,3]
265 var mydict = {foo: "bar"}
266
267 var top = {k: mylist, k2: mylist, k3: mydict, k4: mydict}
268
269 # BUG!
270 json write (top, space=0)
271
272 ## STDOUT:
273 {"k":[1,2,3],"k2":[1,2,3],"k3":{"foo":"bar"},"k4":{"foo":"bar"}}
274 ## END
275
276 #### json read doesn't accept u'' or b'' strings
277
278 json read <<EOF
279 {"key": u'val'}
280 EOF
281 echo status=$?
282
283 #pp test_ (_reply)
284
285 json read <<EOF
286 {"key": b'val'}
287 EOF
288 echo status=$?
289
290 ## STDOUT:
291 status=1
292 status=1
293 ## END
294
295 #### json read doesn't accept comments, but json8 does
296
297 json8 read <<EOF
298 { # comment
299 "key": # zz
300 b'val', # yy
301 "k2": "v2" #
302 }
303 EOF
304 echo status=$?
305
306 json8 write (_reply)
307
308 json read <<EOF
309 {"key": "val"} # comment
310 EOF
311 echo status=$?
312 ## STDOUT:
313 status=0
314 {
315 "key": "val",
316 "k2": "v2"
317 }
318 status=1
319 ## END
320
321
322 #### json write emits Unicode replacement char for binary data \yff
323
324 json write ([3, "foo", $'-\xff\xfe---\xfd=']) > tmp.txt
325
326 # Round trip it for good measure
327 json read < tmp.txt
328
329 json write (_reply)
330
331 ## STDOUT:
332 [
333 3,
334 "foo",
335 "-��---�="
336 ]
337 ## END
338
339 #### json8 accepts j"" prefix, but json doesn't
340
341 var msg = r'j"foo\nbar"'
342
343 echo "$msg" | json read
344 echo json=$?
345 echo
346
347 echo "$msg" | json8 read
348 echo json8=$?
349 pp test_ (_reply)
350 echo
351
352 var msg = r'j"\u0041"'
353 echo "$msg" | json8 read
354 echo json8=$?
355 pp test_ (_reply)
356
357
358 ## STDOUT:
359 json=1
360
361 json8=0
362 (Str) "foo\nbar"
363
364 json8=0
365 (Str) "A"
366 ## END
367
368 #### j"" prefix not accepted in YSH (could be added later)
369
370 shopt -s ysh:all
371
372 # denied by YSH
373 # echo j"\u{7f}"
374
375 var s = j"\u{7f}"
376
377 ## status: 2
378 ## STDOUT:
379 ## END
380
381
382 #### json8 write emits b'' strings for binary data \yff
383
384 json8 write ([3, "foo", $'-\xff\xfe-\xfd='])
385
386 ## STDOUT:
387 [
388 3,
389 "foo",
390 b'-\yff\yfe-\yfd='
391 ]
392 ## END
393
394
395 #### json8 write bytes vs unicode string
396
397 u=$'mu \u03bc \x01 \" \\ \b\f\n\r\t'
398 u2=$'\x01\x1f' # this is a valid unicode string
399
400 b=$'\xff' # this isn't valid unicode
401
402 json8 write (u)
403 json8 write (u2)
404
405 json8 write (b)
406
407 ## STDOUT:
408 "mu μ \u0001 \" \\ \b\f\n\r\t"
409 "\u0001\u001f"
410 b'\yff'
411 ## END
412
413 #### JSON \/ escapes supported
414
415 msg='"\/"'
416
417 echo "$msg" | python3 -c 'import json, sys; print(json.load(sys.stdin))'
418
419 echo "$msg" | json read
420 echo reply=$_reply
421
422 j8="b'\\/'"
423 echo "$msg" | json read
424 echo reply=$_reply
425
426
427 ## STDOUT:
428 /
429 reply=/
430 reply=/
431 ## END
432
433 #### JSON string can have unescaped ' and J8 string can have unescaped "
434
435 json read <<EOF
436 "'"
437 EOF
438
439 pp test_ (_reply)
440
441 json8 read <<EOF
442 u'"'
443 EOF
444
445 pp test_ (_reply)
446
447 ## STDOUT:
448 (Str) "'"
449 (Str) "\""
450 ## END
451
452
453 #### J8 supports superfluous \" escapes, but JSON doesn't support \' escapes
454
455 json8 read <<'EOF'
456 b'\"'
457 EOF
458 echo reply=$_reply
459
460 json8 read <<'EOF'
461 b'\'\'\b\f\n\r\t\"\\'
462 EOF
463 pp test_ (_reply)
464
465 # Suppress traceback
466 python3 -c 'import json, sys; print(json.load(sys.stdin))' 2>/dev/null <<'EOF'
467 "\'"
468 EOF
469 echo python3=$?
470
471 json read <<'EOF'
472 "\'"
473 EOF
474 echo json=$?
475
476 ## STDOUT:
477 reply="
478 (Str) "''\b\f\n\r\t\"\\"
479 python3=1
480 json=1
481 ## END
482
483 #### Escaping uses \u0001 in "", but \u{1} in b''
484
485 s1=$'\x01'
486 s2=$'\x01\xff\x1f' # byte string
487
488 json8 write (s1)
489 json8 write (s2)
490
491 ## STDOUT:
492 "\u0001"
493 b'\u{1}\yff\u{1f}'
494 ## END
495
496
497 #### json8 read
498
499 echo '{ }' | json8 read
500 pp test_ (_reply)
501
502 echo '[ ]' | json8 read
503 pp test_ (_reply)
504
505 echo '[42]' | json8 read
506 pp test_ (_reply)
507
508 echo '[true, false]' | json8 read
509 pp test_ (_reply)
510
511 echo '{"k": "v"}' | json8 read
512 pp test_ (_reply)
513
514 echo '{"k": null}' | json8 read
515 pp test_ (_reply)
516
517 echo '{"k": 1, "k2": 2}' | json8 read
518 pp test_ (_reply)
519
520 echo "{u'k': {b'k2': null}}" | json8 read
521 pp test_ (_reply)
522
523 echo '{"k": {"k2": "v2"}, "k3": "backslash \\ \" \n line 2 \u03bc "}' | json8 read
524 pp test_ (_reply)
525
526 json8 read (&x) <<'EOF'
527 {u'k': {u'k2': u'v2'}, u'k3': u'backslash \\ \" \n line 2 \u{3bc} '}
528 EOF
529 pp test_ (x)
530
531 ## STDOUT:
532 (Dict) {}
533 (List) []
534 (List) [42]
535 (List) [true,false]
536 (Dict) {"k":"v"}
537 (Dict) {"k":null}
538 (Dict) {"k":1,"k2":2}
539 (Dict) {"k":{"k2":null}}
540 (Dict) {"k":{"k2":"v2"},"k3":"backslash \\ \" \n line 2 μ "}
541 (Dict) {"k":{"k2":"v2"},"k3":"backslash \\ \" \n line 2 μ "}
542 ## END
543
544 #### json8 round trip
545
546 var obj = [42, 1.5, null, true, "hi", b'\yff\yfe\b\n""']
547
548 json8 write (obj, space=0) > j
549
550 cat j
551
552 json8 read < j
553
554 json8 write (_reply)
555
556 ## STDOUT:
557 [42,1.5,null,true,"hi",b'\yff\yfe\b\n""']
558 [
559 42,
560 1.5,
561 null,
562 true,
563 "hi",
564 b'\yff\yfe\b\n""'
565 ]
566 ## END
567
568 #### json round trip (regression)
569
570 var d = {
571 short: '-v', long: '--verbose', type: null, default: '', help: 'Enable verbose logging'
572 }
573
574 json write (d) | json read
575
576 pp test_ (_reply)
577
578 ## STDOUT:
579 (Dict) {"short":"-v","long":"--verbose","type":null,"default":"","help":"Enable verbose logging"}
580 ## END
581
582 #### round trip: decode surrogate pair and encode
583
584 var j = r'"\ud83e\udd26"'
585 echo $j | json read (&c1)
586
587 json write (c1)
588
589 var j = r'"\uD83E\uDD26"'
590 echo $j | json read (&c2)
591
592 json write (c2)
593
594 # Not a surrogate pair
595 var j = r'"\u0001\u0002"'
596 echo $j | json read (&c3)
597
598 json write (c3)
599
600 var j = r'"\u0100\u0101\u0102"'
601 echo $j | json read (&c4)
602
603 json write (c4)
604
605 ## STDOUT:
606 "🤦"
607 "🤦"
608 "\u0001\u0002"
609 "ĀāĂ"
610 ## END
611
612 #### round trip: decode surrogate half and encode
613
614 shopt -s ysh:upgrade
615
616 for j in '"\ud83e"' '"\udd26"' {
617 var s = fromJson(j)
618 write -- "$j"
619 pp test_ (s)
620
621 write -n 'json '; json write (s)
622
623 write -n 'json8 '; json8 write (s)
624
625 echo
626 }
627
628 ## STDOUT:
629 "\ud83e"
630 (Str) b'\yed\ya0\ybe'
631 json "\ud83e"
632 json8 b'\yed\ya0\ybe'
633
634 "\udd26"
635 (Str) b'\yed\yb4\ya6'
636 json "\udd26"
637 json8 b'\yed\yb4\ya6'
638
639 ## END
640
641 #### toJson() toJson8()
642
643 var obj = [42, 1.5, null, true, "hi", b'\yf0']
644
645 echo $[toJson(obj)]
646 echo $[toJson8(obj)]
647
648 var obj2 = [3, 4]
649 echo $[toJson(obj2, space=0)] # same as the default
650 echo $[toJson8(obj2, space=0)]
651
652 echo $[toJson(obj2, space=2)]
653 echo $[toJson8(obj2, space=2)]
654
655 # fully specify this behavior
656 echo $[toJson(obj2, space=-2)]
657 echo $[toJson8(obj2, space=-2)]
658
659 ## STDOUT:
660 [42,1.5,null,true,"hi","�"]
661 [42,1.5,null,true,"hi",b'\yf0']
662 [3,4]
663 [3,4]
664 [
665 3,
666 4
667 ]
668 [
669 3,
670 4
671 ]
672 [3,4]
673 [3,4]
674 ## END
675
676 #### fromJson() fromJson8()
677
678 var m1 = '[42,1.5,null,true,"hi"]'
679
680 # JSON8 message
681 var m2 = '[42,1.5,null,true,"hi",' ++ "u''" ++ ']'
682
683 pp test_ (fromJson8(m1))
684 pp test_ (fromJson(m1))
685
686 pp test_ (fromJson8(m2))
687 pp test_ (fromJson(m2)) # fails
688
689 ## status: 4
690 ## STDOUT:
691 (List) [42,1.5,null,true,"hi"]
692 (List) [42,1.5,null,true,"hi"]
693 (List) [42,1.5,null,true,"hi",""]
694 ## END
695
696 #### User can handle errors - toJson() toJson8()
697 shopt -s ysh:upgrade
698
699 var obj = []
700 call obj->append(obj)
701
702 try {
703 echo $[toJson(obj)]
704 }
705 echo status=$_status
706 echo "encode error $[_error.message]" | sed 's/0x[a-f0-9]\+/(object id)/'
707
708 try { # use different style
709 echo $[toJson8( /d+/ )]
710 }
711 echo status=$_status
712 echo "encode error $[_error.message]"
713
714 # This makes the interpreter fail with a message
715 echo $[toJson(obj)]
716
717 ## status: 4
718 ## STDOUT:
719 status=4
720 encode error Can't encode List (object id) in object cycle
721 status=4
722 encode error Can't serialize object of type Eggex
723 ## END
724
725 #### User can handle errors - fromJson() fromJson8()
726 shopt -s ysh:upgrade
727
728 var message ='[42,1.5,null,true,"hi"'
729
730 try {
731 var obj = fromJson(message)
732 }
733 echo status=$_status
734 echo "decode error $[_error.message]" | egrep -o '.*Expected.*RBracket'
735
736 try {
737 var obj = fromJson8(message)
738 }
739 echo status=$_status
740 echo "decode error $[_error.message]" | egrep -o '.*Expected.*RBracket'
741
742 try {
743 var obj = fromJson('[+]')
744 }
745 echo "positions $[_error.start_pos] - $[_error.end_pos]"
746
747 # This makes the interpreter fail with a message
748 var obj = fromJson(message)
749
750 ## status: 4
751 ## STDOUT:
752 status=4
753 decode error Expected Id.J8_RBracket
754 status=4
755 decode error Expected Id.J8_RBracket
756 positions 1 - 2
757 ## END
758
759
760 #### ASCII control chars can't appear literally in messages
761 shopt -s ysh:upgrade
762
763 var message=$'"\x01"'
764 #echo $message | od -c
765
766 try {
767 var obj = fromJson(message)
768 }
769 echo status=$_status
770 echo "$[_error.message]" | egrep -o 'ASCII control chars'
771
772 ## STDOUT:
773 status=4
774 ASCII control chars
775 ## END
776
777
778 #### \yff can't appear in u'' code strings (command)
779
780 shopt -s ysh:upgrade
781
782 echo -n b'\yfd' | od -A n -t x1
783 echo -n u'\yfd' | od -A n -t x1
784
785 ## status: 2
786 ## STDOUT:
787 fd
788 ## END
789
790 #### \yff can't appear in u'' code strings (expr)
791
792 var x = b'\yfe'
793 write -n -- $x | od -A n -t x1
794
795 var x = u'\yfe'
796 write -n -- $x | od -A n -t x1
797
798 ## status: 2
799 ## STDOUT:
800 fe
801 ## END
802
803 #### \yff can't appear in u'' multiline code strings
804
805 shopt -s ysh:upgrade
806
807 echo -n b'''\yfc''' | od -A n -t x1
808 echo -n u'''\yfd''' | od -A n -t x1
809
810 ## status: 2
811 ## STDOUT:
812 fc
813 ## END
814
815 #### \yff can't appear in u'' data strings
816
817 #shopt -s ysh:upgrade
818
819 json8 read (&b) <<'EOF'
820 b'\yfe'
821 EOF
822 pp test_ (b)
823
824 json8 read (&u) <<'EOF'
825 u'\yfe'
826 EOF
827 pp test_ (u) # undefined
828
829 ## status: 1
830 ## STDOUT:
831 (Str) b'\yfe'
832 ## END
833
834 #### \u{dc00} can't be in surrogate range in code (command)
835
836 shopt -s ysh:upgrade
837
838 echo -n u'\u{dc00}' | od -A n -t x1
839
840 ## status: 2
841 ## STDOUT:
842 ## END
843
844 #### \u{dc00} can't be in surrogate range in code (expr)
845
846 shopt -s ysh:upgrade
847
848 var x = u'\u{dc00}'
849 echo $x | od -A n -t x1
850
851 ## status: 2
852 ## STDOUT:
853 ## END
854
855 #### \u{dc00} can't be in surrogate range in data
856
857 json8 read <<'EOF'
858 ["long string", u'hello \u{d7ff}', "other"]
859 EOF
860 echo status=$?
861
862 json8 read <<'EOF'
863 ["long string", u'hello \u{d800}', "other"]
864 EOF
865 echo status=$?
866
867 json8 read <<'EOF'
868 ["long string", u'hello \u{dfff}', "other"]
869 EOF
870 echo status=$?
871
872 json8 read <<'EOF'
873 ["long string", u'hello \u{e000}', "other"]
874 EOF
875 echo status=$?
876
877
878 ## STDOUT:
879 status=0
880 status=1
881 status=1
882 status=0
883 ## END
884
885
886 #### Inf is encoded as null, like JavaScript
887
888 # WRONG LOCATION! Gah
889 #var x = fromJson(repeat('123', 20))
890
891 shopt --set ysh:upgrade
892
893 source $LIB_YSH/list.ysh
894
895 # Create inf
896 var big = repeat('12345678', 100) ++ '.0'
897 #pp test_ (s)
898 var inf = fromJson(big)
899 var neg_inf = fromJson('-' ++ big)
900
901 # Can be printed
902 pp test_ (inf)
903 pp test_ (neg_inf)
904 echo --
905
906 # Can't be serialized
907 try {
908 json write (inf)
909 }
910 echo error=$[_error.code]
911
912 try {
913 json write (neg_inf)
914 }
915 echo error=$[_error.code]
916
917 echo --
918 echo $[toJson(inf)]
919 echo $[toJson(neg_inf)]
920
921 ## STDOUT:
922 (Float) INFINITY
923 (Float) -INFINITY
924 --
925 null
926 error=0
927 null
928 error=0
929 --
930 null
931 null
932 ## END
933
934 #### NaN is encoded as null, like JavaScript
935
936 pp test_ (NAN)
937
938 json write (NAN)
939
940 echo $[toJson(NAN)]
941
942 ## STDOUT:
943 (Float) NAN
944 null
945 null
946 ## END
947
948
949 #### Invalid UTF-8 in JSON is rejected
950
951 echo $'"\xff"' | json read
952 echo status=$?
953
954 echo $'"\xff"' | json8 read
955 echo status=$?
956
957 echo $'\xff' | json read
958 echo status=$?
959
960 echo $'\xff' | json8 read
961 echo status=$?
962
963 ## STDOUT:
964 status=1
965 status=1
966 status=1
967 status=1
968 ## END
969
970 #### Invalid JSON in J8 is rejected
971
972 json8 read <<EOF
973 b'$(echo -e -n '\xff')'
974 EOF
975 echo status=$?
976
977 json8 read <<EOF
978 u'$(echo -e -n '\xff')'
979 EOF
980 echo status=$?
981
982 ## STDOUT:
983 status=1
984 status=1
985 ## END
986
987 #### '' means the same thing as u''
988
989 echo "''" | json8 read
990 pp test_ (_reply)
991
992 echo "'\u{3bc}'" | json8 read
993 pp test_ (_reply)
994
995 echo "'\yff'" | json8 read
996 echo status=$?
997
998 ## STDOUT:
999 (Str) ""
1000 (Str) "μ"
1001 status=1
1002 ## END
1003
1004 #### decode integer larger than 2^32
1005
1006 json=$(( 1 << 33 ))
1007 echo $json
1008
1009 echo $json | json read
1010 pp test_ (_reply)
1011
1012 ## STDOUT:
1013 8589934592
1014 (Int) 8589934592
1015 ## END
1016
1017 #### decode integer larger than 2^64
1018
1019 $SH <<'EOF'
1020 json read <<< '123456789123456789123456789'
1021 echo status=$?
1022 pp test_ (_reply)
1023 EOF
1024
1025 $SH <<'EOF'
1026 json read <<< '-123456789123456789123456789'
1027 echo status=$?
1028 pp test_ (_reply)
1029 EOF
1030
1031 echo ok
1032
1033 ## STDOUT:
1034 status=1
1035 status=1
1036 ok
1037 ## END
1038
1039
1040 #### round trip: read/write with ysh
1041
1042 var file = "$REPO_ROOT/spec/testdata/bug.json"
1043 #cat $file
1044 cat $file | json read (&cfg)
1045 json write (cfg) > ysh-json
1046
1047 diff -u $file ysh-json
1048 echo diff=$?
1049
1050 ## STDOUT:
1051 diff=0
1052 ## END
1053
1054 #### round trip: read/write with ysh, read/write with Python 3 (bug regression)
1055
1056 var file = "$REPO_ROOT/spec/testdata/bug.json"
1057 #cat $file
1058 cat $file | json read (&cfg)
1059 json write (cfg) > ysh-json
1060
1061 cat ysh-json | python3 -c \
1062 'import json, sys; obj = json.load(sys.stdin); json.dump(obj, sys.stdout, indent=2); print()' \
1063 > py-json
1064
1065 diff -u $file py-json
1066 echo diff=$?
1067
1068 ## STDOUT:
1069 diff=0
1070 ## END
1071
1072 #### Encoding bytes that don't hit UTF8_REJECT immediately (bug fix)
1073
1074 var x = $'\xce'
1075 json8 write (x)
1076 declare -p x
1077 echo
1078
1079 var y = $'\xbc'
1080 json8 write (y)
1081 declare -p y
1082 echo
1083
1084 var z = $'\xf0\x9f\xa4\xff'
1085 json8 write (z)
1086 declare -p z
1087
1088 ## STDOUT:
1089 b'\yce'
1090 declare -- x=$'\xce'
1091
1092 b'\ybc'
1093 declare -- y=$'\xbc'
1094
1095 b'\yf0\y9f\ya4\yff'
1096 declare -- z=$'\xf0\x9f\xa4\xff'
1097 ## END
1098
1099 #### NIL8 token in JSON / JSON8
1100
1101 echo "(" | json read
1102 echo status=$?
1103
1104 echo ")" | json8 read
1105 echo status=$?
1106
1107 ## STDOUT:
1108 status=1
1109 status=1
1110 ## END
1111
1112 #### Data after internal NUL (issue #2026)
1113
1114 $SH <<'EOF'
1115 pp test_ (fromJson(b'123\y00abc'))
1116 EOF
1117 echo status=$?
1118
1119 $SH <<'EOF'
1120 pp test_ (fromJson(b'123\y01abc'))
1121 EOF
1122 echo status=$?
1123
1124 $SH <<'EOF'
1125 shopt --set ysh:upgrade # b'' syntax
1126 json read <<< b'123\y00abc'
1127 EOF
1128 echo status=$?
1129
1130 $SH <<'EOF'
1131 shopt --set ysh:upgrade # b'' syntax
1132 json read <<< b'123\y01abc'
1133 EOF
1134 echo status=$?
1135
1136 ## STDOUT:
1137 status=4
1138 status=4
1139 status=1
1140 status=1
1141 ## END
1142
1143 #### Float too big
1144
1145 $SH <<'EOF'
1146 json read <<< '123456789123456789123456789.12345e67890'
1147 echo status=$?
1148 pp test_ (_reply)
1149 EOF
1150
1151 $SH <<'EOF'
1152 json read <<< '-123456789123456789123456789.12345e67890'
1153 echo status=$?
1154 pp test_ (_reply)
1155 EOF
1156
1157 ## STDOUT:
1158 status=0
1159 (Float) INFINITY
1160 status=0
1161 (Float) -INFINITY
1162 ## END
1163
1164 #### Many [[[ , but not too many
1165
1166 shopt -s ysh:upgrade
1167
1168 proc pairs(n) {
1169 var m = int(n) # TODO: 1 .. n should auto-convert?
1170
1171 for i in (1 ..< m) {
1172 write -n -- '['
1173 }
1174 for i in (1 ..< m) {
1175 write -n -- ']'
1176 }
1177 }
1178
1179 # This is all Python can handle; C++ can handle more
1180 msg=$(pairs 50)
1181
1182 #echo $msg
1183
1184 echo "$msg" | json read
1185 pp test_ (_reply)
1186 echo len=$[len(_reply)]
1187
1188 ## STDOUT:
1189 (List) [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
1190 len=1
1191 ## END
1192
1193
1194 #### Too many opening [[[ - blocking stack
1195
1196 python2 -c 'print("[" * 10000)' | json read
1197 pp test_ (_reply)
1198
1199 python2 -c 'print("{" * 10000)' | json read
1200 pp test_ (_reply)
1201
1202 ## STDOUT:
1203 ## END
1204
1205 #### BashArray can be serialized
1206
1207 declare -a empty_array
1208
1209 declare -a array=(x y)
1210 array[5]=z
1211
1212 json write (empty_array)
1213 json write (array)
1214
1215 ## STDOUT:
1216 {
1217 "type": "BashArray",
1218 "data": {}
1219 }
1220 {
1221 "type": "BashArray",
1222 "data": {
1223 "0": "x",
1224 "1": "y",
1225 "5": "z"
1226 }
1227 }
1228 ## END
1229
1230 #### BashAssoc can be serialized
1231
1232 declare -A empty_assoc
1233
1234 declare -A assoc=([foo]=bar [42]=43)
1235
1236 json write (empty_assoc)
1237 json write (assoc)
1238
1239 ## STDOUT:
1240 {
1241 "type": "BashAssoc",
1242 "data": {}
1243 }
1244 {
1245 "type": "BashAssoc",
1246 "data": {
1247 "foo": "bar",
1248 "42": "43"
1249 }
1250 }
1251 ## END