OILS / spec / ysh-json.test.sh View on Github | oilshell.org

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