From da91878939f2d33467a75e08a1fc577c14e73b7e Mon Sep 17 00:00:00 2001 From: John Kerl Date: Sun, 9 Jan 2022 11:11:54 -0500 Subject: [PATCH] Distinguish between JSON and JSON Lines formats (#844) * Draw a distinction between JSON and JSON Lines formats * Add JSON Lines to on-line help example * Have JSON format default to --jlistwrap and --jvstack * Update test cases for --jlistwrap output for JSON output format * Have JSON format default to --jlistwrap and --jvstack for --{X}2j as well * Make --jlistwrap / --jvstack as legacy flags, since now --json and --jsonl * Add --c2l, --l2c, etc. command-line flags * docmods for JSON Lines * Update regression-test cases for JSON / JSON Lines distinction --- README.md | 8 +- docs/src/10min.md | 31 +- docs/src/10min.md.in | 21 +- docs/src/features.md | 14 +- docs/src/features.md.in | 14 +- docs/src/file-formats.md | 112 ++++-- docs/src/file-formats.md.in | 56 +-- docs/src/flatten-unflatten.md | 20 +- docs/src/glossary.md | 8 + docs/src/glossary.md.in | 8 + docs/src/index.md | 2 +- docs/src/index.md.in | 2 +- docs/src/keystroke-savers.md | 4 +- docs/src/manpage.md | 64 ++-- docs/src/manpage.txt | 64 ++-- docs/src/miller-programming-language.md | 20 +- docs/src/new-in-miller-6.md | 65 +++- docs/src/new-in-miller-6.md.in | 61 ++- docs/src/online-help.md | 1 - docs/src/operating-on-all-records.md | 22 +- docs/src/record-heterogeneity.md | 26 +- docs/src/record-heterogeneity.md.in | 8 +- docs/src/reference-dsl-operators.md | 10 + docs/src/reference-main-data-types.md | 12 +- docs/src/reference-main-flag-list.md | 20 +- docs/src/reference-verbs.md | 38 +- docs/src/repl.md | 8 +- docs/src/scripting.md | 30 +- docs/src/sorting.md | 4 + docs/src/special-symbols-and-formatting.md | 4 +- docs/src/sql-examples.md | 82 ++--- docs/src/sql-examples.md.in | 82 ++--- docs/src/two-pass-algorithms.md | 34 +- internal/pkg/auxents/help/entry.go | 18 +- internal/pkg/cli/option_parse.go | 346 +++++++++++++++--- internal/pkg/cli/option_types.go | 20 +- man/manpage.txt | 64 ++-- man/mlr.1 | 74 ++-- test/cases/dsl-array-map-indexing/0010/expout | 2 + test/cases/dsl-array-map-indexing/0011/expout | 2 + test/cases/dsl-array-map-indexing/0012/expout | 2 + test/cases/dsl-array-map-indexing/0013/expout | 2 + test/cases/dsl-arrayify/0001/expout | 2 + test/cases/dsl-arrayify/0002/expout | 2 + test/cases/dsl-arrayify/0003/expout | 2 + test/cases/dsl-arrayify/0004/expout | 2 + test/cases/dsl-arrayify/0005/expout | 2 + test/cases/dsl-clean-whitespace/0001/expout | 32 +- test/cases/dsl-clean-whitespace/0002/expout | 32 +- test/cases/dsl-clean-whitespace/0003/expout | 32 +- test/cases/dsl-clean-whitespace/0004/expout | 32 +- test/cases/dsl-clean-whitespace/0005/expout | 32 +- test/cases/dsl-clean-whitespace/0006/expout | 32 +- test/cases/dsl-clean-whitespace/0007/expout | 32 +- test/cases/dsl-clean-whitespace/0008/expout | 32 +- test/cases/dsl-clean-whitespace/0009/expout | 32 +- .../expout | 8 +- .../expout | 4 +- .../expout | 4 +- .../expout | 2 + .../0031-no-indexed-lashed-emit-maps/expout | 8 +- .../0041-no-indexed-lashed-emitp-maps/expout | 2 + .../expout | 4 +- .../expout | 8 +- .../expout | 8 +- .../expout | 8 +- .../expout | 16 +- .../expout | 16 +- .../expout | 4 +- .../0061-at-indexed-lashed-emit-maps/expout | 8 +- .../0062-over-indexed-lashed-emit-maps/expout | 8 +- .../expout | 4 +- .../expout | 8 +- .../expout | 8 +- .../expout | 8 +- .../expout | 16 +- .../expout | 16 +- .../expout | 4 +- .../0081-at-indexed-lashed-emitp-maps/expout | 8 +- .../expout | 8 +- test/cases/dsl-flatten-unflatten/0004/expout | 8 +- test/cases/dsl-flatten-unflatten/0005/expout | 8 +- test/cases/dsl-flatten-unflatten/0007/expout | 2 + test/cases/dsl-flatten-unflatten/0008/expout | 2 + test/cases/dsl-flatten-unflatten/0009/expout | 2 + test/cases/dsl-functional-tests/0051/expout | 2 + test/cases/dsl-indexing/0002/expout | 14 +- test/cases/dsl-indexing/0003/expout | 8 +- test/cases/dsl-indexing/0004/expout | 8 +- test/cases/dsl-indexing/0005/expout | 26 +- test/cases/dsl-indexing/0006/expout | 8 +- test/cases/dsl-indexing/0007/expout | 8 +- test/cases/dsl-indexing/0008/expout | 8 +- test/cases/dsl-indexing/0014/expout | 8 +- test/cases/dsl-indexing/0015/expout | 8 +- test/cases/dsl-indexing/0016/expout | 2 + test/cases/dsl-indexing/0017/expout | 8 +- test/cases/dsl-indexing/0018/expout | 8 +- test/cases/dsl-indexing/0019/expout | 8 +- test/cases/dsl-indexing/0020/expout | 8 +- test/cases/dsl-indexing/0021/expout | 8 +- .../dsl-json-collection-output/0001/expout | 2 + .../dsl-json-collection-output/0002/expout | 2 + .../dsl-json-collection-output/0003/expout | 2 + .../dsl-json-collection-output/0004/expout | 2 + .../dsl-json-collection-output/0005/expout | 2 + .../dsl-json-collection-output/0006/expout | 2 + .../dsl-json-collection-output/0007/expout | 2 + .../dsl-json-collection-output/0008/expout | 2 + .../dsl-json-collection-output/0009/expout | 2 + .../dsl-json-collection-output/0010/expout | 2 + .../dsl-json-collection-output/0011/expout | 2 + .../dsl-json-collection-output/0012/expout | 2 + .../dsl-json-collection-output/0013/expout | 2 + .../dsl-json-collection-output/0014/expout | 2 + .../dsl-json-collection-output/0015/expout | 2 + .../dsl-json-collection-output/0016/expout | 2 + .../dsl-json-collection-output/0017/expout | 2 + .../dsl-json-collection-output/0018/expout | 2 + .../dsl-json-collection-output/0019/expout | 2 + .../dsl-json-collection-output/0020/expout | 2 + .../dsl-json-collection-output/0021/expout | 2 + .../dsl-json-collection-output/0022/expout | 2 + .../dsl-json-collection-output/0023/expout | 2 + .../dsl-json-collection-output/0024/expout | 2 + .../dsl-json-parse-json-stringify/0001/expout | 2 + .../dsl-json-parse-json-stringify/0002/expout | 2 + .../dsl-json-parse-json-stringify/0003/expout | 2 + .../dsl-json-parse-json-stringify/0006/expout | 2 + .../dsl-json-parse-json-stringify/0007/expout | 2 + test/cases/dsl-lhs-indexing/0001/expout | 4 +- test/cases/dsl-lhs-indexing/0002/expout | 4 +- test/cases/dsl-lhs-indexing/0003/expout | 4 +- test/cases/dsl-lhs-indexing/0004/expout | 4 +- test/cases/dsl-lhs-indexing/0005/expout | 4 +- test/cases/dsl-lhs-indexing/0006/expout | 4 +- test/cases/dsl-lhs-indexing/0007/expout | 4 +- test/cases/dsl-lhs-indexing/0008/expout | 4 +- test/cases/dsl-lhs-indexing/0009/expout | 4 +- test/cases/dsl-lhs-indexing/0010/expout | 4 +- test/cases/dsl-lhs-indexing/0011/expout | 4 +- test/cases/dsl-lhs-indexing/0012/expout | 4 +- test/cases/dsl-lhs-indexing/0013/expout | 4 +- .../0001/expout | 2 + .../0002/expout | 2 + .../0003/expout | 2 + .../0004/expout | 2 + test/cases/dsl-map-dot/0001/expout | 2 + test/cases/dsl-map-dot/0002/expout | 2 + test/cases/dsl-map-dot/0003/expout | 2 + test/cases/dsl-map-dot/0004/expout | 2 + .../dsl-mapsum-mapdiff-mapexcept/0031/expout | 2 + .../dsl-mapsum-mapdiff-mapexcept/0032/expout | 2 + test/cases/dsl-min-max-types/0001/expout | 2 + test/cases/dsl-min-max-types/0002/expout | 2 + test/cases/dsl-min-max-types/0003/expout | 2 + test/cases/dsl-min-max-types/0004/expout | 2 + test/cases/dsl-multi-index/0001/expout | 2 + test/cases/dsl-multi-index/0002/expout | 2 + test/cases/dsl-output-redirects/0070/expout | 20 +- test/cases/dsl-output-redirects/0071/expout | 2 + test/cases/dsl-redirects/0004/out.expect | 20 +- test/cases/dsl-redirects/0008/out.eks.expect | 6 +- test/cases/dsl-redirects/0008/out.hat.expect | 2 + test/cases/dsl-redirects/0008/out.pan.expect | 4 +- test/cases/dsl-redirects/0008/out.wye.expect | 4 +- test/cases/dsl-redirects/0008/out.zee.expect | 4 +- test/cases/dsl-redirects/0010/expout | 20 +- .../dsl-redirects/0034/out.ekspan.expect | 2 + .../dsl-redirects/0034/out.ekswye.expect | 2 + .../dsl-redirects/0034/out.ekszee.expect | 2 + .../dsl-redirects/0034/out.hatwye.expect | 2 + .../dsl-redirects/0034/out.panpan.expect | 2 + .../dsl-redirects/0034/out.panwye.expect | 2 + .../dsl-redirects/0034/out.wyepan.expect | 2 + .../dsl-redirects/0034/out.wyewye.expect | 2 + .../dsl-redirects/0034/out.zeepan.expect | 2 + .../dsl-redirects/0034/out.zeewye.expect | 2 + .../dsl-redirects/0041/out.ekspan.expect | 2 + .../dsl-redirects/0041/out.ekswye.expect | 2 + .../dsl-redirects/0041/out.panpan.expect | 2 + .../dsl-redirects/0041/out.wyewye.expect | 2 + .../dsl-redirects/0048/out.ekspan.expect | 4 +- .../dsl-redirects/0048/out.ekswye.expect | 8 +- .../dsl-redirects/0048/out.panpan.expect | 2 + .../dsl-redirects/0048/out.wyewye.expect | 6 +- .../dsl-redirects/0055/out.ekspan.expect | 2 + .../dsl-redirects/0055/out.ekswye.expect | 2 + .../dsl-redirects/0055/out.panpan.expect | 2 + .../dsl-redirects/0055/out.wyewye.expect | 2 + .../dsl-redirects/0062/out.ekspan.expect | 4 +- .../dsl-redirects/0062/out.ekswye.expect | 8 +- .../dsl-redirects/0062/out.panpan.expect | 2 + .../dsl-redirects/0062/out.wyewye.expect | 6 +- .../dsl-redirects/0085/out.ekspan.expect | 2 + .../dsl-redirects/0085/out.ekswye.expect | 2 + .../dsl-redirects/0085/out.panpan.expect | 2 + .../dsl-redirects/0085/out.wyewye.expect | 2 + .../dsl-redirects/0106/out.ekspan.expect | 4 +- .../dsl-redirects/0106/out.ekswye.expect | 8 +- .../dsl-redirects/0106/out.panpan.expect | 2 + .../dsl-redirects/0106/out.wyewye.expect | 6 +- test/cases/dsl-short-circuit/0028/expout | 6 +- test/cases/dsl-slice/0001/expout | 44 +-- test/cases/dsl-slice/0002/expout | 22 +- test/cases/dsl-slice/0003/expout | 22 +- test/cases/dsl-sorts/sorta/expout | 6 +- test/cases/dsl-sorts/sortaf-within/expout | 2 + test/cases/dsl-sorts/sortmf-within/expout | 2 + test/cases/dsl-sorts/sortmk/expout | 6 +- test/cases/dsl-split-join/0023/expout | 8 +- test/cases/dsl-split-join/0024/expout | 8 +- test/cases/dsl-split-join/0025/expout | 8 +- test/cases/dsl-split-join/0026/expout | 8 +- test/cases/dsl-split-join/0027/expout | 8 +- .../0031/expout | 30 +- test/cases/dsl-whitespace/0001/expout | 2 + test/cases/dsl-whitespace/0002/expout | 2 + test/cases/dsl-whitespace/0003/expout | 2 + test/cases/dsl-whitespace/0004/expout | 2 + test/cases/dsl-whitespace/0005/expout | 2 + .../csv-no-dedupe/expout | 2 + test/cases/io-dedupe-field-names/csv/expout | 2 + .../csvlite-no-dedupe/expout | 2 + .../io-dedupe-field-names/csvlite/expout | 2 + .../dkvp-no-dedupe/expout | 2 + test/cases/io-dedupe-field-names/dkvp/expout | 2 + .../json-no-dedupe/expout | 2 + test/cases/io-dedupe-field-names/json/expout | 2 + .../nidx-no-dedupe/expout | 2 + test/cases/io-dedupe-field-names/nidx/expout | 2 + .../pprint-no-dedupe/expout | 2 + .../cases/io-dedupe-field-names/pprint/expout | 2 + .../xtab-no-dedupe/expout | 2 + test/cases/io-dedupe-field-names/xtab/expout | 2 + .../0003/expout | 20 +- .../0010/expout | 20 +- .../0017/expout | 20 +- .../0024/expout | 20 +- .../0039/expout | 20 +- .../0046/expout | 20 +- .../0051/expout | 20 +- test/cases/io-ixs-regex/0001/expout | 4 +- test/cases/io-ixs-regex/0002/expout | 4 +- test/cases/io-json-io/0004/expout | 6 +- test/cases/io-json-io/0005/cmd | 2 +- test/cases/io-json-io/0005/expout | 17 +- test/cases/io-json-io/0006/cmd | 1 - test/cases/io-json-io/0006/expout | 14 - test/cases/io-json-io/0007/cmd | 1 - test/cases/io-json-io/0007/expout | 14 - test/cases/io-json-io/0008/cmd | 1 - test/cases/io-json-io/0009/cmd | 1 - test/cases/io-json-io/0009/expout | 12 - test/cases/io-json-io/0010/cmd | 1 - test/cases/io-json-io/0010/expout | 14 - test/cases/io-json-io/0011/cmd | 2 +- test/cases/io-json-io/0012/cmd | 1 - test/cases/io-json-io/0012/expout | 12 - test/cases/io-json-io/0013/cmd | 1 - test/cases/io-json-io/0013/expout | 12 - test/cases/io-json-io/0014/cmd | 1 - test/cases/io-json-io/0014/expout | 14 - test/cases/io-json-io/0015/cmd | 1 - test/cases/io-json-io/0015/expout | 14 - test/cases/io-json-io/0016/cmd | 1 - test/cases/io-json-io/0016/expout | 12 - test/cases/io-json-io/0017/cmd | 1 - test/cases/io-json-io/0017/expout | 12 - test/cases/io-json-io/0018/cmd | 1 - test/cases/io-json-io/0018/expout | 14 - test/cases/io-json-io/0019/cmd | 1 - test/cases/io-json-io/0019/expout | 14 - test/cases/io-json-io/0020/cmd | 2 +- test/cases/io-json-io/0021/cmd | 2 +- test/cases/io-json-io/0022/cmd | 1 - test/cases/io-json-io/0022/expout | 12 - test/cases/io-json-io/0023/cmd | 1 - test/cases/io-json-io/0025/expout | 2 + test/cases/io-json-io/0026/cmd | 1 - test/cases/io-json-io/0026/expout | 3 - test/cases/io-json-io/0028/cmd | 1 - test/cases/io-json-io/0028/experr | 0 test/cases/io-json-io/0029/cmd | 1 - test/cases/io-json-io/0029/experr | 0 test/cases/io-json-io/0029/expout | 23 -- test/cases/io-json-io/0030/cmd | 1 - test/cases/io-json-io/0030/experr | 0 test/cases/io-json-io/0030/expout | 23 -- test/cases/io-json-io/0031/expout | 4 +- test/cases/io-json-io/0032/expout | 4 +- test/cases/io-json-io/0033/expout | 2 + test/cases/io-json-io/0034/expout | 2 + test/cases/io-json-io/0035/expout | 2 + test/cases/io-jsonl-io/0001/cmd | 1 + .../0006 => io-jsonl-io/0001}/experr | 0 test/cases/io-jsonl-io/0001/expout | 11 + test/cases/io-jsonl-io/0002/cmd | 1 + .../0007 => io-jsonl-io/0002}/experr | 0 test/cases/io-jsonl-io/0002/expout | 11 + test/cases/io-jsonl-io/0003/cmd | 1 + .../0008 => io-jsonl-io/0003}/experr | 0 test/cases/io-jsonl-io/0003/expout | 7 + test/cases/io-jsonl-io/0004/cmd | 1 + .../0009 => io-jsonl-io/0004}/experr | 0 test/cases/io-jsonl-io/0004/expout | 3 + test/cases/io-jsonl-io/0005/cmd | 1 + .../0010 => io-jsonl-io/0005}/experr | 0 test/cases/io-jsonl-io/0005/expout | 3 + test/cases/io-jsonl-io/0011/cmd | 1 + .../0012 => io-jsonl-io/0011}/experr | 0 test/cases/io-jsonl-io/0011/expout | 3 + test/cases/io-jsonl-io/0020/cmd | 1 + .../0013 => io-jsonl-io/0020}/experr | 0 .../0008 => io-jsonl-io/0020}/expout | 0 test/cases/io-jsonl-io/0021/cmd | 1 + .../0014 => io-jsonl-io/0021}/experr | 0 .../0023 => io-jsonl-io/0021}/expout | 0 test/cases/io-jsonl-io/0024/cmd | 1 + .../0015 => io-jsonl-io/0024}/experr | 0 test/cases/io-jsonl-io/0024/expout | 21 ++ test/cases/io-jsonl-io/0025/cmd | 1 + .../0016 => io-jsonl-io/0025}/experr | 0 test/cases/io-jsonl-io/0025/expout | 1 + .../0026 => io-jsonl-io/0025}/input | 0 test/cases/io-jsonl-io/0027/cmd | 1 + .../0017 => io-jsonl-io/0027}/experr | 0 .../0028 => io-jsonl-io/0027}/expout | 0 test/cases/io-jsonl-io/0031/cmd | 1 + .../0018 => io-jsonl-io/0031}/experr | 0 test/cases/io-jsonl-io/0031/expout | 2 + test/cases/io-jsonl-io/0032/cmd | 1 + .../0019 => io-jsonl-io/0032}/experr | 0 test/cases/io-jsonl-io/0032/expout | 2 + test/cases/io-jsonl-io/0033/cmd | 1 + .../0022 => io-jsonl-io/0033}/experr | 0 test/cases/io-jsonl-io/0033/expout | 1 + test/cases/io-jsonl-io/0034/cmd | 1 + .../0023 => io-jsonl-io/0034}/experr | 0 test/cases/io-jsonl-io/0034/expout | 1 + test/cases/io-jsonl-io/0035/cmd | 1 + .../0026 => io-jsonl-io/0035}/experr | 0 test/cases/io-jsonl-io/0035/expout | 1 + .../io-lf-crlf-and-autodetect/0029/expout | 20 +- .../io-lf-crlf-and-autodetect/0030/expout | 20 +- .../io-lf-crlf-and-autodetect/0031/expout | 20 +- .../io-lf-crlf-and-autodetect/0032/expout | 20 +- .../io-lf-crlf-and-autodetect/0037/expout | 20 +- .../io-lf-crlf-and-autodetect/0038/expout | 20 +- .../io-lf-crlf-and-autodetect/0039/expout | 20 +- .../io-lf-crlf-and-autodetect/0040/expout | 20 +- .../io-lf-crlf-and-autodetect/0045/expout | 20 +- .../io-lf-crlf-and-autodetect/0046/expout | 20 +- .../io-lf-crlf-and-autodetect/0047/expout | 20 +- .../io-lf-crlf-and-autodetect/0048/expout | 20 +- .../io-lf-crlf-and-autodetect/0053/expout | 20 +- .../io-lf-crlf-and-autodetect/0054/expout | 20 +- .../io-lf-crlf-and-autodetect/0055/expout | 20 +- .../io-lf-crlf-and-autodetect/0056/expout | 20 +- test/cases/io-multi/0009/expout | 14 +- test/cases/io-multi/0032/expout | 8 +- test/cases/io-multi/0035/expout | 2 + test/cases/io-multi/0036/expout | 4 +- test/cases/io-multi/0037/expout | 8 +- test/cases/io-multi/0038/expout | 4 +- test/cases/io-multi/0043/expout | 6 +- test/cases/io-multi/0044/expout | 6 +- test/cases/io-multi/0045/expout | 6 +- test/cases/io-multi/0046/expout | 6 +- test/cases/io-multi/0047/expout | 4 +- test/cases/io-multi/0048/expout | 4 +- test/cases/io-multi/0049/expout | 2 + test/cases/io-multi/0050/expout | 8 +- test/cases/io-multi/0051/expout | 8 +- test/cases/io-multi/0052/expout | 10 +- test/cases/io-multi/0053/expout | 2 + test/cases/io-multi/0054/expout | 2 + test/cases/io-multi/0055/expout | 4 +- test/cases/io-multi/0056/expout | 6 +- test/cases/io-separator-aliases/0001/expout | 32 +- test/cases/io-separator-aliases/0002/expout | 8 +- test/cases/io-separator-aliases/0003/expout | 8 +- test/cases/io-separator-aliases/0004/expout | 8 +- test/cases/io-separator-aliases/0005/expout | 8 +- test/cases/io-separator-aliases/0006/expout | 32 +- .../0036-buffer-split/expout | 2 + test/cases/output-colorization/0001/expout | 20 +- test/cases/output-colorization/0002/expout | 20 +- test/cases/repl/0007/expout | 6 +- test/cases/repl/0009/expout | 6 +- test/cases/repl/0010/expout | 12 +- test/cases/verb-flatten-unflatten/0004/expout | 2 + test/cases/verb-flatten-unflatten/0005/expout | 2 + test/cases/verb-flatten-unflatten/0008/expout | 2 + test/cases/verb-flatten-unflatten/0009/expout | 2 + test/cases/verb-flatten-unflatten/0010/expout | 2 + test/cases/verb-flatten-unflatten/0011/expout | 2 + test/cases/verb-flatten-unflatten/0013/expout | 2 + test/cases/verb-flatten-unflatten/0014/expout | 2 + test/cases/verb-flatten-unflatten/0015/expout | 2 + test/cases/verb-flatten-unflatten/0016/expout | 2 + test/cases/verb-flatten-unflatten/0018/expout | 2 + test/cases/verb-format-values/0003/expout | 2 + test/cases/verb-join-mixed-format/0001/expout | 8 +- test/cases/verb-join-mixed-format/0004/expout | 8 +- test/cases/verb-join-mixed-format/0007/expout | 8 +- test/cases/verb-join-mixed-format/0010/expout | 8 +- test/cases/verb-join-mixed-format/0013/expout | 8 +- test/cases/verb-join-mixed-format/0016/expout | 8 +- test/cases/verb-join-mixed-format/0019/expout | 8 +- test/cases/verb-join-mixed-format/0022/expout | 8 +- test/cases/verb-join-mixed-format/0025/expout | 8 +- test/cases/verb-join-mixed-format/0026/expout | 8 +- test/cases/verb-join-mixed-format/0027/expout | 8 +- test/cases/verb-join-mixed-format/0028/expout | 8 +- test/cases/verb-join-mixed-format/0029/expout | 8 +- test/cases/verb-join-mixed-format/0030/expout | 8 +- test/cases/verb-join-mixed-format/0031/expout | 8 +- test/cases/verb-join-mixed-format/0032/expout | 8 +- test/cases/verb-join-mixed-format/0033/expout | 8 +- .../0001/expout | 2 + .../0003/expout | 2 + .../0005/expout | 2 + .../0006/expout | 2 + .../0007/expout | 2 + .../0008/expout | 2 + .../0009/expout | 2 + .../0010/expout | 2 + .../0011/expout | 2 + .../0012/expout | 2 + .../0013/expout | 2 + .../0015/expout | 2 + .../0016/expout | 2 + test/cases/verb-regularize/0002/expout | 6 +- test/cases/verb-reshape/0013/expout | 40 +- .../verb-sort-within-records/0002/expout | 6 +- .../verb-sort-within-records/0003/expout | 6 +- todo.txt | 20 + 438 files changed, 2538 insertions(+), 1517 deletions(-) delete mode 100644 test/cases/io-json-io/0006/cmd delete mode 100644 test/cases/io-json-io/0006/expout delete mode 100644 test/cases/io-json-io/0007/cmd delete mode 100644 test/cases/io-json-io/0007/expout delete mode 100644 test/cases/io-json-io/0008/cmd delete mode 100644 test/cases/io-json-io/0009/cmd delete mode 100644 test/cases/io-json-io/0009/expout delete mode 100644 test/cases/io-json-io/0010/cmd delete mode 100644 test/cases/io-json-io/0010/expout delete mode 100644 test/cases/io-json-io/0012/cmd delete mode 100644 test/cases/io-json-io/0012/expout delete mode 100644 test/cases/io-json-io/0013/cmd delete mode 100644 test/cases/io-json-io/0013/expout delete mode 100644 test/cases/io-json-io/0014/cmd delete mode 100644 test/cases/io-json-io/0014/expout delete mode 100644 test/cases/io-json-io/0015/cmd delete mode 100644 test/cases/io-json-io/0015/expout delete mode 100644 test/cases/io-json-io/0016/cmd delete mode 100644 test/cases/io-json-io/0016/expout delete mode 100644 test/cases/io-json-io/0017/cmd delete mode 100644 test/cases/io-json-io/0017/expout delete mode 100644 test/cases/io-json-io/0018/cmd delete mode 100644 test/cases/io-json-io/0018/expout delete mode 100644 test/cases/io-json-io/0019/cmd delete mode 100644 test/cases/io-json-io/0019/expout delete mode 100644 test/cases/io-json-io/0022/cmd delete mode 100644 test/cases/io-json-io/0022/expout delete mode 100644 test/cases/io-json-io/0023/cmd delete mode 100644 test/cases/io-json-io/0026/cmd delete mode 100644 test/cases/io-json-io/0026/expout delete mode 100644 test/cases/io-json-io/0028/cmd delete mode 100644 test/cases/io-json-io/0028/experr delete mode 100644 test/cases/io-json-io/0029/cmd delete mode 100644 test/cases/io-json-io/0029/experr delete mode 100644 test/cases/io-json-io/0029/expout delete mode 100644 test/cases/io-json-io/0030/cmd delete mode 100644 test/cases/io-json-io/0030/experr delete mode 100644 test/cases/io-json-io/0030/expout create mode 100644 test/cases/io-jsonl-io/0001/cmd rename test/cases/{io-json-io/0006 => io-jsonl-io/0001}/experr (100%) create mode 100644 test/cases/io-jsonl-io/0001/expout create mode 100644 test/cases/io-jsonl-io/0002/cmd rename test/cases/{io-json-io/0007 => io-jsonl-io/0002}/experr (100%) create mode 100644 test/cases/io-jsonl-io/0002/expout create mode 100644 test/cases/io-jsonl-io/0003/cmd rename test/cases/{io-json-io/0008 => io-jsonl-io/0003}/experr (100%) create mode 100644 test/cases/io-jsonl-io/0003/expout create mode 100644 test/cases/io-jsonl-io/0004/cmd rename test/cases/{io-json-io/0009 => io-jsonl-io/0004}/experr (100%) create mode 100644 test/cases/io-jsonl-io/0004/expout create mode 100644 test/cases/io-jsonl-io/0005/cmd rename test/cases/{io-json-io/0010 => io-jsonl-io/0005}/experr (100%) create mode 100644 test/cases/io-jsonl-io/0005/expout create mode 100644 test/cases/io-jsonl-io/0011/cmd rename test/cases/{io-json-io/0012 => io-jsonl-io/0011}/experr (100%) create mode 100644 test/cases/io-jsonl-io/0011/expout create mode 100644 test/cases/io-jsonl-io/0020/cmd rename test/cases/{io-json-io/0013 => io-jsonl-io/0020}/experr (100%) rename test/cases/{io-json-io/0008 => io-jsonl-io/0020}/expout (100%) create mode 100644 test/cases/io-jsonl-io/0021/cmd rename test/cases/{io-json-io/0014 => io-jsonl-io/0021}/experr (100%) rename test/cases/{io-json-io/0023 => io-jsonl-io/0021}/expout (100%) create mode 100644 test/cases/io-jsonl-io/0024/cmd rename test/cases/{io-json-io/0015 => io-jsonl-io/0024}/experr (100%) create mode 100644 test/cases/io-jsonl-io/0024/expout create mode 100644 test/cases/io-jsonl-io/0025/cmd rename test/cases/{io-json-io/0016 => io-jsonl-io/0025}/experr (100%) create mode 100644 test/cases/io-jsonl-io/0025/expout rename test/cases/{io-json-io/0026 => io-jsonl-io/0025}/input (100%) create mode 100644 test/cases/io-jsonl-io/0027/cmd rename test/cases/{io-json-io/0017 => io-jsonl-io/0027}/experr (100%) rename test/cases/{io-json-io/0028 => io-jsonl-io/0027}/expout (100%) create mode 100644 test/cases/io-jsonl-io/0031/cmd rename test/cases/{io-json-io/0018 => io-jsonl-io/0031}/experr (100%) create mode 100644 test/cases/io-jsonl-io/0031/expout create mode 100644 test/cases/io-jsonl-io/0032/cmd rename test/cases/{io-json-io/0019 => io-jsonl-io/0032}/experr (100%) create mode 100644 test/cases/io-jsonl-io/0032/expout create mode 100644 test/cases/io-jsonl-io/0033/cmd rename test/cases/{io-json-io/0022 => io-jsonl-io/0033}/experr (100%) create mode 100644 test/cases/io-jsonl-io/0033/expout create mode 100644 test/cases/io-jsonl-io/0034/cmd rename test/cases/{io-json-io/0023 => io-jsonl-io/0034}/experr (100%) create mode 100644 test/cases/io-jsonl-io/0034/expout create mode 100644 test/cases/io-jsonl-io/0035/cmd rename test/cases/{io-json-io/0026 => io-jsonl-io/0035}/experr (100%) create mode 100644 test/cases/io-jsonl-io/0035/expout diff --git a/README.md b/README.md index 84f9887f2..ce2f0b2de 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ # What is Miller? -**Miller is like awk, sed, cut, join, and sort for data formats such as CSV, TSV, tabular JSON and positionally-indexed.** +**Miller is like awk, sed, cut, join, and sort for data formats such as CSV, TSV, JSON, JSON Lines, and positionally-indexed.** # What can Miller do for me? With Miller, you get to use named fields without needing to count positional -indices, using familiar formats such as CSV, TSV, JSON, and +indices, using familiar formats such as CSV, TSV, JSON, JSON Lines, and positionally-indexed. Then, on the fly, you can add new fields which are functions of existing fields, drop fields, sort, aggregate statistically, pretty-print, and more. @@ -18,7 +18,7 @@ the latter is the array, then Miller's natural data structure is the insertion-ordered hash map. * Miller handles a **variety of data formats**, -including but not limited to the familiar **CSV**, **TSV**, and **JSON**. +including but not limited to the familiar **CSV**, **TSV**, and **JSON**/**JSON Lines**. (Miller can handle **positionally-indexed data** too!) In the above image you can see how Miller embraces the common themes of @@ -136,7 +136,7 @@ system’s available RAM, and you can use Miller in **tail -f** contexts. * Miller is **pipe-friendly** and interoperates with the Unix toolkit. * Miller's I/O formats include **tabular pretty-printing**, **positionally - indexed** (Unix-toolkit style), CSV, JSON, and others. + indexed** (Unix-toolkit style), CSV, TSV, JSON, JSON Lines, and others. * Miller does **conversion** between formats. diff --git a/docs/src/10min.md b/docs/src/10min.md index 7a03b2ed5..9f792eddc 100644 --- a/docs/src/10min.md +++ b/docs/src/10min.md @@ -88,6 +88,7 @@ purple,square,false,10,91,72.3735,8.2430 mlr --icsv --ojson tail -n 2 example.csv
+[
 {
   "color": "yellow",
   "shape": "circle",
@@ -96,7 +97,7 @@ purple,square,false,10,91,72.3735,8.2430
   "index": 87,
   "quantity": 63.5058,
   "rate": 8.3350
-}
+},
 {
   "color": "purple",
   "shape": "square",
@@ -106,6 +107,7 @@ purple,square,false,10,91,72.3735,8.2430
   "quantity": 72.3735,
   "rate": 8.2430
 }
+]
 
You can sort on a single field: @@ -592,6 +594,7 @@ Miller supports the following formats: * CSV (comma-separared values) * TSV (tab-separated values) * JSON (JavaScript Object Notation) +* JSON Lines (JSON with one record per line, and no outermost `[...]`) * PPRINT (pretty-printed tabular) * XTAB (vertical-tabular or sideways-tabular) * NIDX (numerically indexed, label-free, with implicit labels `"1"`, `"2"`, etc.) @@ -623,16 +626,22 @@ circle,1,24 circle 1 24 square,0,36 square 0 36 JSON XTAB -{ shape circle - "shape": "circle", flag 1 - "flag": 1, index 24 - "index": 24 . -} shape square -{ flag 0 - "shape": "square", index 36 +[ shape circle +{ flag 1 + "shape": "circle", index 24 + "flag": 1, + "index": 24 shape square +} flag 0 +{ index 36 + "shape": "square", "flag": 0, "index": 36 } +] + +JSON Lines +{ "shape": "circle", "flag": 1, "index": 24 } +{ "shape": "square", "flag": 0, "index": 36 } DKVP shape=circle,flag=1,index=24 @@ -655,6 +664,7 @@ a matter of specifying input-format and output-format flags: mlr --json cat example.json
+[
 {
   "color": "yellow",
   "shape": "triangle",
@@ -663,7 +673,7 @@ a matter of specifying input-format and output-format flags:
   "index": 11,
   "quantity": 43.6498,
   "rate": 9.8870
-}
+},
 {
   "color": "red",
   "shape": "square",
@@ -673,6 +683,7 @@ a matter of specifying input-format and output-format flags:
   "quantity": 79.2778,
   "rate": 0.0130
 }
+]
 
@@ -747,6 +758,7 @@ These transformations are reversible:
 mlr --ijson --oxtab cat data/server-log.json | mlr --ixtab --ojson cat
 
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -768,6 +780,7 @@ These transformations are reversible:
     }
   }
 }
+]
 
See the [flatten/unflatten page](flatten-unflatten.md) for more information. diff --git a/docs/src/10min.md.in b/docs/src/10min.md.in index 33f86da0f..11b6d291d 100644 --- a/docs/src/10min.md.in +++ b/docs/src/10min.md.in @@ -243,6 +243,7 @@ Miller supports the following formats: * CSV (comma-separared values) * TSV (tab-separated values) * JSON (JavaScript Object Notation) +* JSON Lines (JSON with one record per line, and no outermost `[...]`) * PPRINT (pretty-printed tabular) * XTAB (vertical-tabular or sideways-tabular) * NIDX (numerically indexed, label-free, with implicit labels `"1"`, `"2"`, etc.) @@ -274,16 +275,22 @@ circle,1,24 circle 1 24 square,0,36 square 0 36 JSON XTAB -{ shape circle - "shape": "circle", flag 1 - "flag": 1, index 24 - "index": 24 . -} shape square -{ flag 0 - "shape": "square", index 36 +[ shape circle +{ flag 1 + "shape": "circle", index 24 + "flag": 1, + "index": 24 shape square +} flag 0 +{ index 36 + "shape": "square", "flag": 0, "index": 36 } +] + +JSON Lines +{ "shape": "circle", "flag": 1, "index": 24 } +{ "shape": "square", "flag": 0, "index": 36 } DKVP shape=circle,flag=1,index=24 diff --git a/docs/src/features.md b/docs/src/features.md index 9f62d2361..36d4f66ee 100644 --- a/docs/src/features.md +++ b/docs/src/features.md @@ -17,16 +17,16 @@ Quick links: # Features Miller is like awk, sed, cut, join, and sort for **name-indexed data such as -CSV, TSV, and tabular JSON**. You get to work with your data using named +CSV, TSV, JSON, and JSON Lines**. You get to work with your data using named fields, without needing to count positional column indices. -This is something the Unix toolkit always could have done, and arguably -always should have done. It operates on key-value-pair data while the familiar -Unix tools operate on integer-indexed fields: if the natural data structure for -the latter is the array, then Miller's natural data structure is the +This is something the Unix toolkit always could have done, and arguably always +should have done. It operates on key-value-pair data while the familiar Unix +tools operate on integer-indexed fields: if the natural data structure for the +latter is the array, then Miller's natural data structure is the insertion-ordered hash map. This encompasses a **variety of data formats**, -including but not limited to the familiar CSV, TSV, and JSON. (Miller can handle -**positionally-indexed data** as a special case.) +including but not limited to the familiar CSV, TSV, JSON, and JSON Lines. +(Miller can handle **positionally-indexed data** as a special case.) * Miller is **multi-purpose**: it's useful for **data cleaning**, **data reduction**, **statistical reporting**, **devops**, **system administration**, **log-file processing**, **format conversion**, and **database-query post-processing**. diff --git a/docs/src/features.md.in b/docs/src/features.md.in index c914a464f..22b2c5378 100644 --- a/docs/src/features.md.in +++ b/docs/src/features.md.in @@ -1,16 +1,16 @@ # Features Miller is like awk, sed, cut, join, and sort for **name-indexed data such as -CSV, TSV, and tabular JSON**. You get to work with your data using named +CSV, TSV, JSON, and JSON Lines**. You get to work with your data using named fields, without needing to count positional column indices. -This is something the Unix toolkit always could have done, and arguably -always should have done. It operates on key-value-pair data while the familiar -Unix tools operate on integer-indexed fields: if the natural data structure for -the latter is the array, then Miller's natural data structure is the +This is something the Unix toolkit always could have done, and arguably always +should have done. It operates on key-value-pair data while the familiar Unix +tools operate on integer-indexed fields: if the natural data structure for the +latter is the array, then Miller's natural data structure is the insertion-ordered hash map. This encompasses a **variety of data formats**, -including but not limited to the familiar CSV, TSV, and JSON. (Miller can handle -**positionally-indexed data** as a special case.) +including but not limited to the familiar CSV, TSV, JSON, and JSON Lines. +(Miller can handle **positionally-indexed data** as a special case.) * Miller is **multi-purpose**: it's useful for **data cleaning**, **data reduction**, **statistical reporting**, **devops**, **system administration**, **log-file processing**, **format conversion**, and **database-query post-processing**. diff --git a/docs/src/file-formats.md b/docs/src/file-formats.md index 1cbda18d8..3838cb1bc 100644 --- a/docs/src/file-formats.md +++ b/docs/src/file-formats.md @@ -16,7 +16,9 @@ Quick links: # File formats -Miller handles name-indexed data using several formats: some you probably know by name, such as CSV, TSV, and JSON -- and other formats you're likely already seeing and using in your structured data. +Miller handles name-indexed data using several formats: some you probably know +by name, such as CSV, TSV, JSON, and JSON Lines -- and other formats you're likely already +seeing and using in your structured data. Additionally, Miller gives you the option of including comments within your data. @@ -34,22 +36,32 @@ TSV: same but with tabs in places of commas | 4,5,6 | Record 2: "apple":"4", "bat":"5", "cog":"6" +---------------------+ -JSON (sequence or array of objects): +JSON (array of objects): +---------------------+ +| [ | | { | | "apple": 1, | Record 1: "apple":"1", "bat":"2", "cog":"3" | "bat": 2, | | "cog": 3 | -| } | +| }, | | { | -| "dish": { | Record 2: "dish:egg":"7", -| "egg": 7, | "dish:flint":"8", "garlic":"" +| "dish": { | Record 2: "dish.egg":"7", +| "egg": 7, | "dish.flint":"8", "garlic":"" | "flint": 8 | | }, | | "garlic": "" | | } | +| ] | +---------------------+ +JSON Lines (sequence of one-line objects): ++------------------------------------------------+ +| {"apple": 1, "bat": 2, "cog": 3} | +| {"dish": {"egg": 7, "flint": 8}, "garlic": ""} | ++------------------------------------------------+ + Record 1: "apple":"1", "bat":"2", "cog":"3" + Record 2: "dish:egg":"7", "dish:flint":"8", "garlic":"" + PPRINT: pretty-printed tabular +---------------------+ | apple bat cog | @@ -125,11 +137,11 @@ Here are things they have in common: ## JSON -JSON is a format which supports scalars (numbers, strings, boolean, etc.) as -well as "objects" (maps) and "arrays" (lists), while Miller is a tool for -handling **tabular data** only. By *tabular JSON* I mean the data is either a -sequence of one or more objects, or an array consisting of one or more objects. -Miller treats JSON objects as name-indexed records. +[JSON](https://json.org) is a format which supports scalars (numbers, strings, +boolean, etc.) as well as "objects" (maps) and "arrays" (lists), while Miller +is a tool for handling **tabular data** only. By *tabular JSON* I mean the +data is either a sequence of one or more objects, or an array consisting of one +or more objects. Miller treats JSON objects as name-indexed records. This means Miller cannot (and should not) handle arbitrary JSON. In practice, though, Miller can handle single JSON objects as well as list of them. The only @@ -149,30 +161,34 @@ An **array of single-level objects** is, quite simply, **a table**: mlr --json head -n 2 then cut -f color,shape data/json-example-1.json
+[
 {
   "color": "yellow",
   "shape": "triangle"
-}
+},
 {
   "color": "red",
   "shape": "square"
 }
+]
 
 mlr --json head -n 2 then cut -f color,u,v data/json-example-1.json
 
+[
 {
   "color": "yellow",
   "u": 0.632170,
   "v": 0.988721
-}
+},
 {
   "color": "red",
   "u": 0.219668,
   "v": 0.001257
 }
+]
 
Single-level JSON data goes back and forth between JSON and tabular formats @@ -210,9 +226,10 @@ Additionally, Miller can **tabularize nested objects by concatenating keys**. If input as well as output in JSON format, JSON structure is preserved throughout the processing:
-mlr --json --jvstack head -n 2 data/json-example-2.json
+mlr --json head -n 2 data/json-example-2.json
 
+[
 {
   "flag": 1,
   "i": 11,
@@ -226,7 +243,7 @@ input as well as output in JSON format, JSON structure is preserved throughout t
     "w": 0.436498,
     "x": 5.798188
   }
-}
+},
 {
   "flag": 1,
   "i": 15,
@@ -241,6 +258,7 @@ input as well as output in JSON format, JSON structure is preserved throughout t
     "x": 2.944117
   }
 }
+]
 
But if the input format is JSON and the output format is not (or vice versa) then key-concatenation applies: @@ -258,20 +276,7 @@ flag i attributes.color attributes.shape values.u values.v values.w values.x This is discussed in more detail on the page [Flatten/unflatten: JSON vs. tabular formats](flatten-unflatten.md). -### JSON-formatting options - -JSON isn't a parameterized format, so `RS`, `FS`, `PS` aren't specifiable. Nonetheless, you can do the following: - -* Use `--no-jvstack` to print JSON objects one per line. By default, each Miller record (JSON object) is pretty-printed in multi-line format. - -* Use `--jlistwrap` to print the sequence of JSON objects wrapped in an outermost `[` and `]`. By default, these aren't printed. - - - -* Use `--jflatsep yourseparatorhere` to specify the string used for key concatenation: this defaults to a single dot. +Use `--jflatsep yourseparatorhere` to specify the string used for key concatenation: this defaults to a single dot. ### JSON-in-CSV @@ -279,6 +284,55 @@ It's quite common to have CSV data which contains stringified JSON as a column. See the [JSON parse and stringify section](reference-main-data-types.md#json-parse-and-stringify) for ways to decode these in Miller. +## JSON Lines + +[JSON Lines](https://jsonlines.org) is similar to JSON, except: + +* UTF-8 encoding must be supported +* There is no outermost `[...]` +* Each record is on a single line + +Miller handles this: + +
+mlr --icsv --ojson head -n 2 example.csv
+
+
+[
+{
+  "color": "yellow",
+  "shape": "triangle",
+  "flag": "true",
+  "k": 1,
+  "index": 11,
+  "quantity": 43.6498,
+  "rate": 9.8870
+},
+{
+  "color": "red",
+  "shape": "square",
+  "flag": "true",
+  "k": 2,
+  "index": 15,
+  "quantity": 79.2778,
+  "rate": 0.0130
+}
+]
+
+ +
+mlr --icsv --ojsonl head -n 2 example.csv
+
+
+{"color": "yellow", "shape": "triangle", "flag": "true", "k": 1, "index": 11, "quantity": 43.6498, "rate": 9.8870}
+{"color": "red", "shape": "square", "flag": "true", "k": 2, "index": 15, "quantity": 79.2778, "rate": 0.0130}
+
+ +Note that for _input_ data, either is acceptable: whether you use `--ijson` or `--ijsonl`, Miller +won't reject your input data for lack of outermost `[...]`, nor will it reject your data for placement +of newlines. The difference is on _output_: using `--ojson`, you get outermost `[...]` and pretty-printed +records; using `--ojsonl`, you get no outermost `[...]`, and one line per record. + ## PPRINT: Pretty-printed tabular Miller's pretty-print format is like CSV, but column-aligned. For example, compare @@ -392,7 +446,7 @@ _networkd * 24 24 Network Services /var/networkd /usr/bin/false
 $ grep -v '^#' /etc/passwd | head -n 2 | \
-  mlr --nidx --fs : --ojson --jvstack --jlistwrap \
+  mlr --nidx --fs : --ojson \
     label name,password,uid,gid,gecos,home_dir,shell
 
diff --git a/docs/src/file-formats.md.in b/docs/src/file-formats.md.in
index 699baa8a9..5a17fa91e 100644
--- a/docs/src/file-formats.md.in
+++ b/docs/src/file-formats.md.in
@@ -1,6 +1,8 @@
 # File formats
 
-Miller handles name-indexed data using several formats: some you probably know by name, such as CSV, TSV, and JSON -- and other formats you're likely already seeing and using in your structured data.
+Miller handles name-indexed data using several formats: some you probably know
+by name, such as CSV, TSV, JSON, and JSON Lines -- and other formats you're likely already
+seeing and using in your structured data.
 
 Additionally, Miller gives you the option of including comments within your data.
 
@@ -47,11 +49,11 @@ Here are things they have in common:
 
 ## JSON
 
-JSON is a format which supports scalars (numbers, strings, boolean, etc.) as
-well as "objects" (maps) and "arrays" (lists), while Miller is a tool for
-handling **tabular data** only.  By *tabular JSON* I mean the data is either a
-sequence of one or more objects, or an array consisting of one or more objects.
-Miller treats JSON objects as name-indexed records.
+[JSON](https://json.org) is a format which supports scalars (numbers, strings,
+boolean, etc.) as well as "objects" (maps) and "arrays" (lists), while Miller
+is a tool for handling **tabular data** only.  By *tabular JSON* I mean the
+data is either a sequence of one or more objects, or an array consisting of one
+or more objects.  Miller treats JSON objects as name-indexed records.
 
 This means Miller cannot (and should not) handle arbitrary JSON.  In practice,
 though, Miller can handle single JSON objects as well as list of them. The only
@@ -92,7 +94,7 @@ Additionally, Miller can **tabularize nested objects by concatenating keys**. If
 input as well as output in JSON format, JSON structure is preserved throughout the processing:
 
 GENMD-RUN-COMMAND
-mlr --json --jvstack head -n 2 data/json-example-2.json
+mlr --json head -n 2 data/json-example-2.json
 GENMD-EOF
 
 But if the input format is JSON and the output format is not (or vice versa) then key-concatenation applies:
@@ -103,20 +105,7 @@ GENMD-EOF
 
 This is discussed in more detail on the page [Flatten/unflatten: JSON vs. tabular formats](flatten-unflatten.md).
 
-### JSON-formatting options
-
-JSON isn't a parameterized format, so `RS`, `FS`, `PS` aren't specifiable. Nonetheless, you can do the following:
-
-* Use `--no-jvstack` to print JSON objects one per line.  By default, each Miller record (JSON object) is pretty-printed in multi-line format.
-
-* Use `--jlistwrap` to print the sequence of JSON objects wrapped in an outermost `[` and `]`. By default, these aren't printed.
-
-
-
-* Use `--jflatsep yourseparatorhere` to specify the string used for key concatenation: this defaults to a single dot.
+Use `--jflatsep yourseparatorhere` to specify the string used for key concatenation: this defaults to a single dot.
 
 ### JSON-in-CSV
 
@@ -124,6 +113,29 @@ It's quite common to have CSV data which contains stringified JSON as a column.
 See the [JSON parse and stringify section](reference-main-data-types.md#json-parse-and-stringify) for ways to
 decode these in Miller.
 
+## JSON Lines
+
+[JSON Lines](https://jsonlines.org) is similar to JSON, except:
+
+* UTF-8 encoding must be supported
+* There is no outermost `[...]`
+* Each record is on a single line
+
+Miller handles this:
+
+GENMD-RUN-COMMAND
+mlr --icsv --ojson head -n 2 example.csv
+GENMD-EOF
+
+GENMD-RUN-COMMAND
+mlr --icsv --ojsonl head -n 2 example.csv
+GENMD-EOF
+
+Note that for _input_ data, either is acceptable: whether you use `--ijson` or `--ijsonl`, Miller
+won't reject your input data for lack of outermost `[...]`, nor will it reject your data for placement
+of newlines. The difference is on _output_: using `--ojson`, you get outermost `[...]` and pretty-printed
+records; using `--ojsonl`, you get no outermost `[...]`, and one line per record.
+
 ## PPRINT: Pretty-printed tabular
 
 Miller's pretty-print format is like CSV, but column-aligned.  For example, compare
@@ -197,7 +209,7 @@ GENMD-EOF
 
 GENMD-CARDIFY-HIGHLIGHT-THREE
 $ grep -v '^#' /etc/passwd | head -n 2 | \
-  mlr --nidx --fs : --ojson --jvstack --jlistwrap \
+  mlr --nidx --fs : --ojson \
     label name,password,uid,gid,gecos,home_dir,shell
 [
 {
diff --git a/docs/src/flatten-unflatten.md b/docs/src/flatten-unflatten.md
index 4db94d896..7a3c138d2 100644
--- a/docs/src/flatten-unflatten.md
+++ b/docs/src/flatten-unflatten.md
@@ -181,13 +181,14 @@ a,b.x,b.y
 mlr --ijson --ocsv cat data/map-values.json | mlr --icsv --ojson cat
 
+[
 {
   "a": 1,
   "b": {
     "x": 2,
     "y": 3
   }
-}
+},
 {
   "a": 4,
   "b": {
@@ -195,6 +196,7 @@ a,b.x,b.y
     "y": 6
   }
 }
+]
 
## Converting arrays between JSON and non-JSON @@ -284,14 +286,16 @@ a,b.1,b.2 mlr --ijson --ocsv cat data/array-values.json | mlr --icsv --ojson cat
+[
 {
   "a": 1,
   "b": [2, 3]
-}
+},
 {
   "a": 4,
   "b": [5, 6]
 }
+]
 
## Auto-inferencing of arrays on unflatten @@ -314,9 +318,11 @@ a.1,a.2,a.3 mlr --c2j cat data/consecutive.csv
+[
 {
   "a": [4, 5, 6]
 }
+]
 
@@ -331,6 +337,7 @@ a.1,a.3,a.5
 mlr --c2j cat data/non-consecutive.csv
 
+[
 {
   "a": {
     "1": 4,
@@ -338,6 +345,7 @@ a.1,a.3,a.5
     "5": 6
   }
 }
+]
 
## Manual control @@ -373,16 +381,18 @@ Using JSON output, we can see that `splita` has produced an array-valued field n mlr --icsv --ojson --from data/hostnames.csv put '$components = splita($host, ".")'
+[
 {
   "host": "apoapsis.east.our.org",
   "status": "up",
   "components": ["apoapsis", "east", "our", "org"]
-}
+},
 {
   "host": "nadir.west.our.org",
   "status": "down",
   "components": ["nadir", "west", "our", "org"]
 }
+]
 
Using CSV output, with default auto-flatten, we get `components.1` through `components.4`: @@ -452,18 +462,20 @@ leave `b` JSON-stringified: mlr --ixtab --ojson json-parse -f a data/hostnames.xtab
+[
 {
   "host": "apoapsis.east.our.org",
   "status": "up",
   "a": ["apoapsis", "east", "our", "org"],
   "b": "[\"apoapsis\", \"east\", \"our\", \"org\"]"
-}
+},
 {
   "host": "nadir.west.our.org",
   "status": "down",
   "a": ["nadir", "west", "our", "org"],
   "b": "[\"nadir\", \"west\", \"our\", \"org\"]"
 }
+]
 
See also the diff --git a/docs/src/glossary.md b/docs/src/glossary.md index 21a0624eb..96a99fc2e 100644 --- a/docs/src/glossary.md +++ b/docs/src/glossary.md @@ -427,6 +427,14 @@ Stands for _input record separator_. See the [separators page](reference-main-se Stands for [_JavaScript object notation_](https://www.json.org). A popular [file format](file-formats.md#json) for tabular data supported by Miller. +## JSON Lines + +A [file format](file-formats.md#json-lines) related to +[JSON](https://www.json.org), supported by Miller. Key points are that every +record is an object written on a single line, without need to be wrapped an +outermost list. This format helps people interoperate with non-JSON-aware +tools in the [Unix toolkit](#unix-toolkit) which generally operate on lines. + ## key The string index in a [map](#map). Also, the name of a field in a [record](#record). diff --git a/docs/src/glossary.md.in b/docs/src/glossary.md.in index 4e7ae7961..d14428643 100644 --- a/docs/src/glossary.md.in +++ b/docs/src/glossary.md.in @@ -411,6 +411,14 @@ Stands for _input record separator_. See the [separators page](reference-main-se Stands for [_JavaScript object notation_](https://www.json.org). A popular [file format](file-formats.md#json) for tabular data supported by Miller. +## JSON Lines + +A [file format](file-formats.md#json-lines) related to +[JSON](https://www.json.org), supported by Miller. Key points are that every +record is an object written on a single line, without need to be wrapped an +outermost list. This format helps people interoperate with non-JSON-aware +tools in the [Unix toolkit](#unix-toolkit) which generally operate on lines. + ## key The string index in a [map](#map). Also, the name of a field in a [record](#record). diff --git a/docs/src/index.md b/docs/src/index.md index 99051aed3..e0d996a21 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -16,7 +16,7 @@ Quick links: # Introduction -**Miller is a command-line tool for querying, shaping, and reformatting data files in various formats including CSV, TSV, and JSON.** +**Miller is a command-line tool for querying, shaping, and reformatting data files in various formats including CSV, TSV, JSON, and JSON Lines.** In several senses, Miller is more than one tool: diff --git a/docs/src/index.md.in b/docs/src/index.md.in index 60a570d98..c61374595 100644 --- a/docs/src/index.md.in +++ b/docs/src/index.md.in @@ -1,6 +1,6 @@ # Introduction -**Miller is a command-line tool for querying, shaping, and reformatting data files in various formats including CSV, TSV, and JSON.** +**Miller is a command-line tool for querying, shaping, and reformatting data files in various formats including CSV, TSV, JSON, and JSON Lines.** In several senses, Miller is more than one tool: diff --git a/docs/src/keystroke-savers.md b/docs/src/keystroke-savers.md index 268f92b0d..c6dc27f1a 100644 --- a/docs/src/keystroke-savers.md +++ b/docs/src/keystroke-savers.md @@ -33,6 +33,7 @@ red square true 2 15 79.2778 0.0130 mlr --c2j head -n 2 example.csv
+[
 {
   "color": "yellow",
   "shape": "triangle",
@@ -41,7 +42,7 @@ red    square   true 2 15    79.2778  0.0130
   "index": 11,
   "quantity": 43.6498,
   "rate": 9.8870
-}
+},
 {
   "color": "red",
   "shape": "square",
@@ -51,6 +52,7 @@ red    square   true 2 15    79.2778  0.0130
   "quantity": 79.2778,
   "rate": 0.0130
 }
+]
 
You can get the full list [here](file-formats.md#data-conversion-keystroke-savers). diff --git a/docs/src/manpage.md b/docs/src/manpage.md index db011ee69..de4fb8f71 100644 --- a/docs/src/manpage.md +++ b/docs/src/manpage.md @@ -70,22 +70,32 @@ FILE FORMATS | 4,5,6 | Record 2: "apple":"4", "bat":"5", "cog":"6" +---------------------+ - JSON (sequence or array of objects): + JSON (array of objects): +---------------------+ + | [ | | { | | "apple": 1, | Record 1: "apple":"1", "bat":"2", "cog":"3" | "bat": 2, | | "cog": 3 | - | } | + | }, | | { | - | "dish": { | Record 2: "dish:egg":"7", - | "egg": 7, | "dish:flint":"8", "garlic":"" + | "dish": { | Record 2: "dish.egg":"7", + | "egg": 7, | "dish.flint":"8", "garlic":"" | "flint": 8 | | }, | | "garlic": "" | | } | + | ] | +---------------------+ + JSON Lines (sequence of one-line objects): + +------------------------------------------------+ + | {"apple": 1, "bat": 2, "cog": 3} | + | {"dish": {"egg": 7, "flint": 8}, "garlic": ""} | + +------------------------------------------------+ + Record 1: "apple":"1", "bat":"2", "cog":"3" + Record 2: "dish:egg":"7", "dish:flint":"8", "garlic":"" + PPRINT: pretty-printed tabular +---------------------+ | apple bat cog | @@ -139,7 +149,6 @@ HELP OPTIONS mlr help file-format-flags mlr help flatten-unflatten-flags mlr help format-conversion-keystroke-saver-flags - mlr help json-only-flags mlr help legacy-flags mlr help miscellaneous-flags mlr help output-colorization-flags @@ -350,6 +359,7 @@ FILE-FORMAT FLAGS --gen-step, and --gen-stop values. See also the seqgen verb, which is more useful/intuitive. --ijson Use JSON format for input data. + --ijsonl Use JSON Lines format for input data. --inidx Use NIDX format for input data. --io {format name} Use format name for input and output data. For example: `--io csv` is the same as `--csv`. @@ -359,12 +369,14 @@ FILE-FORMAT FLAGS --iusv or --iusvlite Use USV format for input data. --ixtab Use XTAB format for input data. --json or -j Use JSON format for input and output data. + --jsonl Use JSON Lines format for input and output data. --nidx Use NIDX format for input and output data. --oasv or --oasvlite Use ASV format for output data. --ocsv Use CSV format for output data. --ocsvlite Use CSV-lite format for output data. --odkvp Use DKVP format for output data. --ojson Use JSON format for output data. + --ojsonl Use JSON Lines format for output data. --omd Use markdown-tabular format for output data. --onidx Use NIDX format for output data. --opprint Use PPRINT format for output data. @@ -406,37 +418,32 @@ FLATTEN-UNFLATTEN FLAGS FORMAT-CONVERSION KEYSTROKE-SAVER FLAGS As keystroke-savers for format-conversion you may use the following. - The letters c, t, j, d, n, x, p, and m refer to formats CSV, TSV, DKVP, NIDX, - JSON, XTAB, PPRINT, and markdown, respectively. Note that markdown format is - available for output only. + The letters c, t, j, l, d, n, x, p, and m refer to formats CSV, TSV, DKVP, NIDX, + JSON, JSON Lines, XTAB, PPRINT, and markdown, respectively. Note that markdown + format is available for output only. - | In\out | CSV | TSV | JSON | DKVP | NIDX | XTAB | PPRINT | Markdown | + | In\out | CSV | TSV | JSON | JSONL | DKVP | NIDX | XTAB | PPRINT | Markdown | +--------+-------+-------+--------+--------+--------+--------+--------+----------+ - | CSV | | --c2t | --c2j | --c2d | --c2n | --c2x | --c2p | --c2m | - | TSV | --t2c | | --t2j | --t2d | --t2n | --t2x | --t2p | --t2m | - | JSON | --j2c | --j2t | | --j2d | --j2n | --j2x | --j2p | --j2m | - | DKVP | --d2c | --d2t | --d2j | | --d2n | --d2x | --d2p | --d2m | - | NIDX | --n2c | --n2t | --n2j | --n2d | | --n2x | --n2p | --n2m | - | XTAB | --x2c | --x2t | --x2j | --x2d | --x2n | | --x2p | --x2m | - | PPRINT | --p2c | --p2t | --p2j | --p2d | --p2n | --p2x | | --p2m | + | CSV | | --c2t | --c2j | --c2l | --c2d | --c2n | --c2x | --c2p | --c2m | + | TSV | --t2c | | --t2j | --t2l | --t2d | --t2n | --t2x | --t2p | --t2m | + | JSON | --j2c | --j2t | | --j2l | --j2d | --j2n | --j2x | --j2p | --j2m | + | JSONL | --l2c | --l2t | | | --l2d | --l2n | --l2x | --l2p | --l2m | + | DKVP | --d2c | --d2t | --d2j | --d2l | | --d2n | --d2x | --d2p | --d2m | + | NIDX | --n2c | --n2t | --n2j | --n2l | --n2d | | --n2x | --n2p | --n2m | + | XTAB | --x2c | --x2t | --x2j | --x2l | --x2d | --x2n | | --x2p | --x2m | + | PPRINT | --p2c | --p2t | --p2j | --p2l | --p2d | --p2n | --p2x | | --p2m | -p Keystroke-saver for `--nidx --fs space --repifs`. -T Keystroke-saver for `--nidx --fs tab`. -JSON-ONLY FLAGS - These are flags which are applicable to JSON format. - - --jlistwrap or --jl Wrap JSON output in outermost `[ ]`. - --jvstack Put one key-value pair per line for JSON output - (multi-line output). - --no-jvstack Put objects/arrays all on one line for JSON output. - LEGACY FLAGS These are flags which don't do anything in the current Miller version. They are accepted as no-op flags in order to keep old scripts from breaking. --jknquoteint Type information from JSON input files is now preserved throughout the processing stream. + --jlistwrap or --jl Wrap JSON output in outermost `[ ]`. This is the + default for JSON output format. --jquoteall Type information from JSON input files is now preserved throughout the processing stream. --json-fatal-arrays-on-input @@ -448,8 +455,15 @@ LEGACY FLAGS --jsonx The `--jvstack` flag is now default true in Miller 6. --jvquoteall Type information from JSON input files is now preserved throughout the processing stream. + --jvstack Put one key-value pair per line for JSON output + (multi-line output). This is the default for JSON + output format. --mmap Miller no longer uses memory-mapping to access data files. + --no-jlistwrap Wrap JSON output in outermost `[ ]`. This is the + default for JSON Lines output format. + --no-jvstack Put objects/arrays all on one line for JSON output. + This is the default for JSON Lines output format. --no-mmap Miller no longer uses memory-mapping to access data files. --ojsonx The `--jvstack` flag is now default true in Miller 6. @@ -3040,5 +3054,5 @@ SEE ALSO - 2022-01-08 MILLER(1) + 2022-01-09 MILLER(1) diff --git a/docs/src/manpage.txt b/docs/src/manpage.txt index 8da5f15af..ce925ef04 100644 --- a/docs/src/manpage.txt +++ b/docs/src/manpage.txt @@ -49,22 +49,32 @@ FILE FORMATS | 4,5,6 | Record 2: "apple":"4", "bat":"5", "cog":"6" +---------------------+ - JSON (sequence or array of objects): + JSON (array of objects): +---------------------+ + | [ | | { | | "apple": 1, | Record 1: "apple":"1", "bat":"2", "cog":"3" | "bat": 2, | | "cog": 3 | - | } | + | }, | | { | - | "dish": { | Record 2: "dish:egg":"7", - | "egg": 7, | "dish:flint":"8", "garlic":"" + | "dish": { | Record 2: "dish.egg":"7", + | "egg": 7, | "dish.flint":"8", "garlic":"" | "flint": 8 | | }, | | "garlic": "" | | } | + | ] | +---------------------+ + JSON Lines (sequence of one-line objects): + +------------------------------------------------+ + | {"apple": 1, "bat": 2, "cog": 3} | + | {"dish": {"egg": 7, "flint": 8}, "garlic": ""} | + +------------------------------------------------+ + Record 1: "apple":"1", "bat":"2", "cog":"3" + Record 2: "dish:egg":"7", "dish:flint":"8", "garlic":"" + PPRINT: pretty-printed tabular +---------------------+ | apple bat cog | @@ -118,7 +128,6 @@ HELP OPTIONS mlr help file-format-flags mlr help flatten-unflatten-flags mlr help format-conversion-keystroke-saver-flags - mlr help json-only-flags mlr help legacy-flags mlr help miscellaneous-flags mlr help output-colorization-flags @@ -329,6 +338,7 @@ FILE-FORMAT FLAGS --gen-step, and --gen-stop values. See also the seqgen verb, which is more useful/intuitive. --ijson Use JSON format for input data. + --ijsonl Use JSON Lines format for input data. --inidx Use NIDX format for input data. --io {format name} Use format name for input and output data. For example: `--io csv` is the same as `--csv`. @@ -338,12 +348,14 @@ FILE-FORMAT FLAGS --iusv or --iusvlite Use USV format for input data. --ixtab Use XTAB format for input data. --json or -j Use JSON format for input and output data. + --jsonl Use JSON Lines format for input and output data. --nidx Use NIDX format for input and output data. --oasv or --oasvlite Use ASV format for output data. --ocsv Use CSV format for output data. --ocsvlite Use CSV-lite format for output data. --odkvp Use DKVP format for output data. --ojson Use JSON format for output data. + --ojsonl Use JSON Lines format for output data. --omd Use markdown-tabular format for output data. --onidx Use NIDX format for output data. --opprint Use PPRINT format for output data. @@ -385,37 +397,32 @@ FLATTEN-UNFLATTEN FLAGS FORMAT-CONVERSION KEYSTROKE-SAVER FLAGS As keystroke-savers for format-conversion you may use the following. - The letters c, t, j, d, n, x, p, and m refer to formats CSV, TSV, DKVP, NIDX, - JSON, XTAB, PPRINT, and markdown, respectively. Note that markdown format is - available for output only. + The letters c, t, j, l, d, n, x, p, and m refer to formats CSV, TSV, DKVP, NIDX, + JSON, JSON Lines, XTAB, PPRINT, and markdown, respectively. Note that markdown + format is available for output only. - | In\out | CSV | TSV | JSON | DKVP | NIDX | XTAB | PPRINT | Markdown | + | In\out | CSV | TSV | JSON | JSONL | DKVP | NIDX | XTAB | PPRINT | Markdown | +--------+-------+-------+--------+--------+--------+--------+--------+----------+ - | CSV | | --c2t | --c2j | --c2d | --c2n | --c2x | --c2p | --c2m | - | TSV | --t2c | | --t2j | --t2d | --t2n | --t2x | --t2p | --t2m | - | JSON | --j2c | --j2t | | --j2d | --j2n | --j2x | --j2p | --j2m | - | DKVP | --d2c | --d2t | --d2j | | --d2n | --d2x | --d2p | --d2m | - | NIDX | --n2c | --n2t | --n2j | --n2d | | --n2x | --n2p | --n2m | - | XTAB | --x2c | --x2t | --x2j | --x2d | --x2n | | --x2p | --x2m | - | PPRINT | --p2c | --p2t | --p2j | --p2d | --p2n | --p2x | | --p2m | + | CSV | | --c2t | --c2j | --c2l | --c2d | --c2n | --c2x | --c2p | --c2m | + | TSV | --t2c | | --t2j | --t2l | --t2d | --t2n | --t2x | --t2p | --t2m | + | JSON | --j2c | --j2t | | --j2l | --j2d | --j2n | --j2x | --j2p | --j2m | + | JSONL | --l2c | --l2t | | | --l2d | --l2n | --l2x | --l2p | --l2m | + | DKVP | --d2c | --d2t | --d2j | --d2l | | --d2n | --d2x | --d2p | --d2m | + | NIDX | --n2c | --n2t | --n2j | --n2l | --n2d | | --n2x | --n2p | --n2m | + | XTAB | --x2c | --x2t | --x2j | --x2l | --x2d | --x2n | | --x2p | --x2m | + | PPRINT | --p2c | --p2t | --p2j | --p2l | --p2d | --p2n | --p2x | | --p2m | -p Keystroke-saver for `--nidx --fs space --repifs`. -T Keystroke-saver for `--nidx --fs tab`. -JSON-ONLY FLAGS - These are flags which are applicable to JSON format. - - --jlistwrap or --jl Wrap JSON output in outermost `[ ]`. - --jvstack Put one key-value pair per line for JSON output - (multi-line output). - --no-jvstack Put objects/arrays all on one line for JSON output. - LEGACY FLAGS These are flags which don't do anything in the current Miller version. They are accepted as no-op flags in order to keep old scripts from breaking. --jknquoteint Type information from JSON input files is now preserved throughout the processing stream. + --jlistwrap or --jl Wrap JSON output in outermost `[ ]`. This is the + default for JSON output format. --jquoteall Type information from JSON input files is now preserved throughout the processing stream. --json-fatal-arrays-on-input @@ -427,8 +434,15 @@ LEGACY FLAGS --jsonx The `--jvstack` flag is now default true in Miller 6. --jvquoteall Type information from JSON input files is now preserved throughout the processing stream. + --jvstack Put one key-value pair per line for JSON output + (multi-line output). This is the default for JSON + output format. --mmap Miller no longer uses memory-mapping to access data files. + --no-jlistwrap Wrap JSON output in outermost `[ ]`. This is the + default for JSON Lines output format. + --no-jvstack Put objects/arrays all on one line for JSON output. + This is the default for JSON Lines output format. --no-mmap Miller no longer uses memory-mapping to access data files. --ojsonx The `--jvstack` flag is now default true in Miller 6. @@ -3019,4 +3033,4 @@ SEE ALSO - 2022-01-08 MILLER(1) + 2022-01-09 MILLER(1) diff --git a/docs/src/miller-programming-language.md b/docs/src/miller-programming-language.md index 8a3770d17..ed41a4f6c 100644 --- a/docs/src/miller-programming-language.md +++ b/docs/src/miller-programming-language.md @@ -162,9 +162,11 @@ sum mlr --c2j --from example.csv put -q 'begin { @sum = 0 } @sum += $quantity; end {emit @sum}'
+[
 {
   "sum": 652.7185
 }
+]
 
@@ -176,10 +178,12 @@ sum
 '
 
+[
 {
   "count": 10,
   "sum": 652.7185
 }
+]
 
We'll see in the documentation for [stats1](reference-verbs.md#stats1) that there's a lower-keystroking way to get counts and sums of things: @@ -188,10 +192,12 @@ We'll see in the documentation for [stats1](reference-verbs.md#stats1) that ther mlr --c2j --from example.csv stats1 -a sum,count -f quantity
+[
 {
   "quantity_sum": 652.7185,
   "quantity_count": 10
 }
+]
 
So, take this sum/count example as an indication of the kinds of things you can do using Miller's programming language. @@ -397,35 +403,39 @@ For example, you can sum up all the `$a` values across records without having to mlr --json cat absent-example.json
+[
 {
   "a": 1,
   "b": 2
-}
+},
 {
   "c": 3
-}
+},
 {
   "a": 4,
   "b": 5
 }
+]
 
 mlr --json put '@sum_of_a += $a; end {emit @sum_of_a}' absent-example.json
 
+[
 {
   "a": 1,
   "b": 2
-}
+},
 {
   "c": 3
-}
+},
 {
   "a": 4,
   "b": 5
-}
+},
 {
   "sum_of_a": 5
 }
+]
 
diff --git a/docs/src/new-in-miller-6.md b/docs/src/new-in-miller-6.md index 327c57e46..f859b3479 100644 --- a/docs/src/new-in-miller-6.md +++ b/docs/src/new-in-miller-6.md @@ -167,7 +167,7 @@ purple,triangle,false,7,65,80.1405,5.8240 ## Data processing -### Improved JSON support, and arrays +### Improved JSON / JSON Lines support, and arrays Arrays are now supported in Miller's `put`/`filter` programming language, as described in the [Arrays reference](reference-main-arrays.md). (Also, `array` is @@ -175,11 +175,19 @@ now a keyword so this is no longer usable as a local-variable or UDF name.) JSON support is improved: -* Direct support for arrays means that you can now use Miller to process more JSON files. -* Streamable JSON parsing: Miller's internal record-processing pipeline starts as soon as the first record is read (which was already the case for other file formats). This means that, unless records are wrapped with outermost `[...]`, Miller now handles JSON in `tail -f` contexts like it does for other file formats. +* Direct support for arrays means that you can now use Miller to process more JSON files than ever before. +* Streamable JSON parsing: Miller's internal record-processing pipeline starts as soon as the first record is read (which was already the case for other file formats). This means that, unless records are wrapped with outermost `[...]`, Miller now handles JSON / JSON Lines in `tail -f` contexts like it does for other file formats. * Flatten/unflatten -- conversion of JSON nested data structures (arrays and/or maps in record values) to/from non-JSON formats is a powerful new feature, discussed in the page [Flatten/unflatten: JSON vs. tabular formats](flatten-unflatten.md). * Since types are better handled now, the workaround flags `--jvquoteall` and `--jknquoteint` no longer have meaning -- although they're accepted as no-ops at the command line for backward compatibility. -* Multi-line JSON is now the default. Use `--no-jvstack` for Miller-5 style, which required `--jvstack` to get multiline output. + +JSON vs JSON Lines: + +* Miller 5 accepted input records either with or without enclosing `[...]`; on output, by default it produced single-line records without outermost `[...]`. Miller 5 let you customize output formatting using `--jvstack` (multi-line records) and `--jlistwrap` (write outermost `[...]`). _Thus, Miller 5's JSON output format, with default flags, was in fact [JSON Lines](file-formats.md#json-lines) all along._ +* In Miller 6, [JSON Lines](file-formats.md#json-lines) is acknowledged explicitly. +* On input, your records are accepted whether or not they have outermost `[...]`, and regardless of line breaks, whether the specified input format is JSON or JSON Lines. (This is similar to [jq](https://stedolan.github.io/jq/).) +* With `--ojson`, output records are written multiline (pretty-printed), with outermost `[...]`. +* With `--ojsonl`, output records are written single-line, without outermost `[...]`. +* This makes `--jvstack` and `--jlistwrap` unnecessary. However, if you want outermost `[...]` with single-line records, you can use `--ojson --no-jvstack`. See also the [Arrays reference](reference-main-arrays.md) for more information. @@ -210,19 +218,23 @@ For example (see [https://github.com/johnkerl/miller/issues/178](https://github. echo '{ "a": "0123" }' | mlr --json cat
+[
 {
   "a": "0123"
 }
+]
 
 echo '{ "x": 1.230, "y": 1.230000000 }' | mlr --json cat
 
+[
 {
   "x": 1.230,
   "y": 1.230000000
 }
+]
 
### Regex support for IFS and IPS @@ -261,24 +273,41 @@ See also the [list of issues tagged with go-port](https://github.com/johnkerl/mi The following differences are rather technical. If they don't sound familiar to you, not to worry! Most users won't be affected by the (relatively minor) changes between Miller 5 and Miller 6. -* Line endings: The `--auto` flag is now ignored. Before, if a file had CR/LF (Windows-style) line endings on input (on any platform), it would have the same on output; likewise, LF (Unix-style) line endings. Now, files with CR/LF or LF line endings are processed on any platform, but the output line-ending is for the platform. E.g. reading CR/LF files on Linux will now produce LF output. -* Since IFS and IPS can be regular expressions now, if your `IFS` or `IPS` is a `.` (which is a regular-expression metacharacter) you can either use `--ifs '\.'` or `--ifs . --no-ifs-regex` (and similarly for `IPS`). Please see the section on [multi-character and regular-expression separators](reference-main-separators.md#multi-character-and-regular-expression-separators). -* JSON formatting: - * `--jvstack` and `--jsonx` (multi-line JSON output) is now the default for JSON; use `--no-jvstack` to suppress it. - * `--jknquoteint` and `jquoteall` are ignored; they were workarounds for the (now much-improved) tyoe-inference and type-tracking in Miller 6. - * `--json-fatal-arrays-on-input`, `--json-map-arrays-on-input`, and `--json-skip-arrays-on-input` are ignored; Miller 6 now supports arrays fully. - * See also `mlr help legacy-flags` or the [legacy-flags reference](reference-main-flag-list.md#legacy-flags). -* Type-inference: - * The `-S` and `-F` flags to `mlr put` and `mlr filter` are ignored, since type-inference is no longer done in `mlr put` and `mlr filter`, but rather, when records are first read. You can use `mlr -S` and `mlr -A`, respectively, instead to control type-inference within the record-readers. - * Octal numbers like `0123` and `07` are type-inferred as string. Use `mlr -O` to infer them as octal integers. Note that `08` and `09` will then infer as deicmal integers. - * Any numbers prefix with `0o`, e.g. `0o377`, are already treated as octal regardless of `mlr -O` -- `mlr -O` only affects how leading-zero integers are handled. - * See also the [miscellaneous-flags reference](reference-main-flag-list.md#miscellaneous-flags). +**Please drop an issue at [https://github.com/johnkerl/miller/issues](https://github.com/johnkerl/miller/issues) with any/all backward-compatibility concerns between Miller 5 and Miller 6.** + +### Line endings + +The `--auto` flag is now ignored. Before, if a file had CR/LF (Windows-style) line endings on input (on any platform), it would have the same on output; likewise, LF (Unix-style) line endings. Now, files with CR/LF or LF line endings are processed on any platform, but the output line-ending is for the platform. E.g. reading CR/LF files on Linux will now produce LF output. + +### IFS and IPS as regular expressions + +IFS and IPS can be regular expressions now. Please see the section on [multi-character and regular-expression separators](reference-main-separators.md#multi-character-and-regular-expression-separators). + +### JSON and JSON Lines formatting + +* `--jknquoteint` and `jquoteall` are ignored; they were workarounds for the (now much-improved) tyoe-inference and type-tracking in Miller 6. +* `--json-fatal-arrays-on-input`, `--json-map-arrays-on-input`, and `--json-skip-arrays-on-input` are ignored; Miller 6 now supports arrays fully. +* See also `mlr help legacy-flags` or the [legacy-flags reference](reference-main-flag-list.md#legacy-flags). +* Miller 5 accepted input records either with or without enclosing `[...]`; on output, by default it produced single-line records without outermost `[...]`. Miller 5 let you customize output formatting using `--jvstack` (multi-line records) and `--jlistwrap` (write outermost `[...]`). _Thus, Miller 5's JSON output format, with default flags, was in fact [JSON Lines](file-formats.md#json-lines) all along._ +* In Miller 6, [JSON Lines](file-formats.md#json-lines) is acknowledged explicitly. +* On input, your records are accepted whether or not they have outermost `[...]`, and regardless of line breaks, whether the specified input format is JSON or JSON Lines. (This is similar to [jq](https://stedolan.github.io/jq/).) +* With `--ojson`, output records are written multiline (pretty-printed), with outermost `[...]`. +* With `--ojsonl`, output records are written single-line, without outermost `[...]`. +* This makes `--jvstack` and `--jlistwrap` unnecessary. However, if you want outermost `[...]` with single-line records, you can use `--ojson --no-jvstack`. + +### Type-inference + +* The `-S` and `-F` flags to `mlr put` and `mlr filter` are ignored, since type-inference is no longer done in `mlr put` and `mlr filter`, but rather, when records are first read. You can use `mlr -S` and `mlr -A`, respectively, instead to control type-inference within the record-readers. +* Octal numbers like `0123` and `07` are type-inferred as string. Use `mlr -O` to infer them as octal integers. Note that `08` and `09` will then infer as deicmal integers. +* Any numbers prefix with `0o`, e.g. `0o377`, are already treated as octal regardless of `mlr -O` -- `mlr -O` only affects how leading-zero integers are handled. +* See also the [miscellaneous-flags reference](reference-main-flag-list.md#miscellaneous-flags). + +### Emit statements + * Emitting a map-valued expression now requires either a temporary variable or the new `emit1` keyword. Please see the [page on emit statements](reference-dsl-output-statements.md#emit1-and-emitemitpemitf) for more information. * By default, field names are deduped for all file formats except JSON. So if you have an input record with `x=8,x=9` then the second field's key is renamed to `x_2` and so on -- the record scans as `x=8,x_2=9`. Use `mlr --no-dedupe-field-names` to suppress this, and have the record be scanned as `x=9`. For JSON, the last duplicated key in an input record is always retained, regardless of `mlr --no-dedupe-field-names`: `{"x":8,"x":9}` scans as if it were `{"x":9}`. -**Please drop an issue at [https://github.com/johnkerl/miller/issues](https://github.com/johnkerl/miller/issues) with any/all backward-compatibility concerns between Miller 5 and Miller 6.** - ## Developer-specific aspects * Miller has been ported from C to Go. Developer notes: [https://github.com/johnkerl/miller/blob/main/README-go-port.md](https://github.com/johnkerl/miller/blob/main/README-go-port.md). diff --git a/docs/src/new-in-miller-6.md.in b/docs/src/new-in-miller-6.md.in index 7e2cc99c7..e0397cc45 100644 --- a/docs/src/new-in-miller-6.md.in +++ b/docs/src/new-in-miller-6.md.in @@ -136,7 +136,7 @@ GENMD-EOF ## Data processing -### Improved JSON support, and arrays +### Improved JSON / JSON Lines support, and arrays Arrays are now supported in Miller's `put`/`filter` programming language, as described in the [Arrays reference](reference-main-arrays.md). (Also, `array` is @@ -144,11 +144,19 @@ now a keyword so this is no longer usable as a local-variable or UDF name.) JSON support is improved: -* Direct support for arrays means that you can now use Miller to process more JSON files. -* Streamable JSON parsing: Miller's internal record-processing pipeline starts as soon as the first record is read (which was already the case for other file formats). This means that, unless records are wrapped with outermost `[...]`, Miller now handles JSON in `tail -f` contexts like it does for other file formats. +* Direct support for arrays means that you can now use Miller to process more JSON files than ever before. +* Streamable JSON parsing: Miller's internal record-processing pipeline starts as soon as the first record is read (which was already the case for other file formats). This means that, unless records are wrapped with outermost `[...]`, Miller now handles JSON / JSON Lines in `tail -f` contexts like it does for other file formats. * Flatten/unflatten -- conversion of JSON nested data structures (arrays and/or maps in record values) to/from non-JSON formats is a powerful new feature, discussed in the page [Flatten/unflatten: JSON vs. tabular formats](flatten-unflatten.md). * Since types are better handled now, the workaround flags `--jvquoteall` and `--jknquoteint` no longer have meaning -- although they're accepted as no-ops at the command line for backward compatibility. -* Multi-line JSON is now the default. Use `--no-jvstack` for Miller-5 style, which required `--jvstack` to get multiline output. + +JSON vs JSON Lines: + +* Miller 5 accepted input records either with or without enclosing `[...]`; on output, by default it produced single-line records without outermost `[...]`. Miller 5 let you customize output formatting using `--jvstack` (multi-line records) and `--jlistwrap` (write outermost `[...]`). _Thus, Miller 5's JSON output format, with default flags, was in fact [JSON Lines](file-formats.md#json-lines) all along._ +* In Miller 6, [JSON Lines](file-formats.md#json-lines) is acknowledged explicitly. +* On input, your records are accepted whether or not they have outermost `[...]`, and regardless of line breaks, whether the specified input format is JSON or JSON Lines. (This is similar to [jq](https://stedolan.github.io/jq/).) +* With `--ojson`, output records are written multiline (pretty-printed), with outermost `[...]`. +* With `--ojsonl`, output records are written single-line, without outermost `[...]`. +* This makes `--jvstack` and `--jlistwrap` unnecessary. However, if you want outermost `[...]` with single-line records, you can use `--ojson --no-jvstack`. See also the [Arrays reference](reference-main-arrays.md) for more information. @@ -219,24 +227,41 @@ See also the [list of issues tagged with go-port](https://github.com/johnkerl/mi The following differences are rather technical. If they don't sound familiar to you, not to worry! Most users won't be affected by the (relatively minor) changes between Miller 5 and Miller 6. -* Line endings: The `--auto` flag is now ignored. Before, if a file had CR/LF (Windows-style) line endings on input (on any platform), it would have the same on output; likewise, LF (Unix-style) line endings. Now, files with CR/LF or LF line endings are processed on any platform, but the output line-ending is for the platform. E.g. reading CR/LF files on Linux will now produce LF output. -* Since IFS and IPS can be regular expressions now, if your `IFS` or `IPS` is a `.` (which is a regular-expression metacharacter) you can either use `--ifs '\.'` or `--ifs . --no-ifs-regex` (and similarly for `IPS`). Please see the section on [multi-character and regular-expression separators](reference-main-separators.md#multi-character-and-regular-expression-separators). -* JSON formatting: - * `--jvstack` and `--jsonx` (multi-line JSON output) is now the default for JSON; use `--no-jvstack` to suppress it. - * `--jknquoteint` and `jquoteall` are ignored; they were workarounds for the (now much-improved) tyoe-inference and type-tracking in Miller 6. - * `--json-fatal-arrays-on-input`, `--json-map-arrays-on-input`, and `--json-skip-arrays-on-input` are ignored; Miller 6 now supports arrays fully. - * See also `mlr help legacy-flags` or the [legacy-flags reference](reference-main-flag-list.md#legacy-flags). -* Type-inference: - * The `-S` and `-F` flags to `mlr put` and `mlr filter` are ignored, since type-inference is no longer done in `mlr put` and `mlr filter`, but rather, when records are first read. You can use `mlr -S` and `mlr -A`, respectively, instead to control type-inference within the record-readers. - * Octal numbers like `0123` and `07` are type-inferred as string. Use `mlr -O` to infer them as octal integers. Note that `08` and `09` will then infer as deicmal integers. - * Any numbers prefix with `0o`, e.g. `0o377`, are already treated as octal regardless of `mlr -O` -- `mlr -O` only affects how leading-zero integers are handled. - * See also the [miscellaneous-flags reference](reference-main-flag-list.md#miscellaneous-flags). +**Please drop an issue at [https://github.com/johnkerl/miller/issues](https://github.com/johnkerl/miller/issues) with any/all backward-compatibility concerns between Miller 5 and Miller 6.** + +### Line endings + +The `--auto` flag is now ignored. Before, if a file had CR/LF (Windows-style) line endings on input (on any platform), it would have the same on output; likewise, LF (Unix-style) line endings. Now, files with CR/LF or LF line endings are processed on any platform, but the output line-ending is for the platform. E.g. reading CR/LF files on Linux will now produce LF output. + +### IFS and IPS as regular expressions + +IFS and IPS can be regular expressions now. Please see the section on [multi-character and regular-expression separators](reference-main-separators.md#multi-character-and-regular-expression-separators). + +### JSON and JSON Lines formatting + +* `--jknquoteint` and `jquoteall` are ignored; they were workarounds for the (now much-improved) tyoe-inference and type-tracking in Miller 6. +* `--json-fatal-arrays-on-input`, `--json-map-arrays-on-input`, and `--json-skip-arrays-on-input` are ignored; Miller 6 now supports arrays fully. +* See also `mlr help legacy-flags` or the [legacy-flags reference](reference-main-flag-list.md#legacy-flags). +* Miller 5 accepted input records either with or without enclosing `[...]`; on output, by default it produced single-line records without outermost `[...]`. Miller 5 let you customize output formatting using `--jvstack` (multi-line records) and `--jlistwrap` (write outermost `[...]`). _Thus, Miller 5's JSON output format, with default flags, was in fact [JSON Lines](file-formats.md#json-lines) all along._ +* In Miller 6, [JSON Lines](file-formats.md#json-lines) is acknowledged explicitly. +* On input, your records are accepted whether or not they have outermost `[...]`, and regardless of line breaks, whether the specified input format is JSON or JSON Lines. (This is similar to [jq](https://stedolan.github.io/jq/).) +* With `--ojson`, output records are written multiline (pretty-printed), with outermost `[...]`. +* With `--ojsonl`, output records are written single-line, without outermost `[...]`. +* This makes `--jvstack` and `--jlistwrap` unnecessary. However, if you want outermost `[...]` with single-line records, you can use `--ojson --no-jvstack`. + +### Type-inference + +* The `-S` and `-F` flags to `mlr put` and `mlr filter` are ignored, since type-inference is no longer done in `mlr put` and `mlr filter`, but rather, when records are first read. You can use `mlr -S` and `mlr -A`, respectively, instead to control type-inference within the record-readers. +* Octal numbers like `0123` and `07` are type-inferred as string. Use `mlr -O` to infer them as octal integers. Note that `08` and `09` will then infer as deicmal integers. +* Any numbers prefix with `0o`, e.g. `0o377`, are already treated as octal regardless of `mlr -O` -- `mlr -O` only affects how leading-zero integers are handled. +* See also the [miscellaneous-flags reference](reference-main-flag-list.md#miscellaneous-flags). + +### Emit statements + * Emitting a map-valued expression now requires either a temporary variable or the new `emit1` keyword. Please see the [page on emit statements](reference-dsl-output-statements.md#emit1-and-emitemitpemitf) for more information. * By default, field names are deduped for all file formats except JSON. So if you have an input record with `x=8,x=9` then the second field's key is renamed to `x_2` and so on -- the record scans as `x=8,x_2=9`. Use `mlr --no-dedupe-field-names` to suppress this, and have the record be scanned as `x=9`. For JSON, the last duplicated key in an input record is always retained, regardless of `mlr --no-dedupe-field-names`: `{"x":8,"x":9}` scans as if it were `{"x":9}`. -**Please drop an issue at [https://github.com/johnkerl/miller/issues](https://github.com/johnkerl/miller/issues) with any/all backward-compatibility concerns between Miller 5 and Miller 6.** - ## Developer-specific aspects * Miller has been ported from C to Go. Developer notes: [https://github.com/johnkerl/miller/blob/main/README-go-port.md](https://github.com/johnkerl/miller/blob/main/README-go-port.md). diff --git a/docs/src/online-help.md b/docs/src/online-help.md index 0216e0cda..0b6d9a674 100644 --- a/docs/src/online-help.md +++ b/docs/src/online-help.md @@ -57,7 +57,6 @@ Flags: mlr help file-format-flags mlr help flatten-unflatten-flags mlr help format-conversion-keystroke-saver-flags - mlr help json-only-flags mlr help legacy-flags mlr help miscellaneous-flags mlr help output-colorization-flags diff --git a/docs/src/operating-on-all-records.md b/docs/src/operating-on-all-records.md index 6da5b05a1..6663f1c18 100644 --- a/docs/src/operating-on-all-records.md +++ b/docs/src/operating-on-all-records.md @@ -68,22 +68,24 @@ after all the input is read. '
+[
 {
   "word": "apple",
   "value": 37
-}
+},
 {
   "word": "ball",
   "value": 28
-}
+},
 {
   "word": "cat",
   "value": 54
-}
+},
 {
   "count": 3,
   "sum": 119
 }
+]
 
And if all we want is the final output and not the input data, we can use `put @@ -103,10 +105,12 @@ And if all we want is the final output and not the input data, we can use `put '
+[
 {
   "count": 3,
   "sum": 119
 }
+]
 
As discussed a bit more on the page on [streaming processing and memory @@ -163,10 +167,12 @@ cat,54 "value": 54 } } +[ { "count": 3, "sum": 119 } +] The downside to this, of course, is that this retains all records (plus data-structure overhead) in memory, so you're limited to processing files that fit in your computer's memory. The upside, though, is that you can do random access over the records using things like @@ -220,10 +226,12 @@ The third option is to retain records in an [array](reference-main-arrays.md), t "value": 54 } ] +[ { "count": 3, "sum": 119 } +] Just as with the retain-as-map approach, the downside is the overhead of @@ -266,6 +274,8 @@ array will have [null-gaps](reference-main-arrays.md) in it: "value": 54 } ] +[ +] You can index `@records` by `@count` rather than `NR` to get a contiguous array: @@ -303,10 +313,12 @@ You can index `@records` by `@count` rather than `NR` to get a contiguous array: "value": 54 } ] +[ { "count": 2, "sum": 91 } +] If you use a map to retain records, then this is a non-issue: maps can retain whatever values you like: @@ -342,10 +354,12 @@ If you use a map to retain records, then this is a non-issue: maps can retain wh "value": 54 } } +[ { "count": 2, "sum": 91 } +] Do note that Miller [maps](reference-main-maps.md) preserve insertion order, so @@ -384,10 +398,12 @@ interested in: "1": 37, "3": 54 } +[ { "count": 2, "sum": 91 } +] ## Sorting diff --git a/docs/src/record-heterogeneity.md b/docs/src/record-heterogeneity.md index 2c796d1df..48b9db7dd 100644 --- a/docs/src/record-heterogeneity.md +++ b/docs/src/record-heterogeneity.md @@ -43,10 +43,10 @@ a,b,c 7,8,9 -It has three records (written here using JSON formatting): +It has three records (written here using JSON Lines formatting):
-mlr --icsv --ojson --no-jvstack cat data/het/hom.csv
+mlr --icsv --ojsonl cat data/het/hom.csv
 
 {"a": 1, "b": 2, "c": 3}
@@ -83,7 +83,7 @@ a,b,c
 
-mlr --icsv --ojson --no-jvstack cat data/het/fillable.csv
+mlr --icsv --ojsonl cat data/het/fillable.csv
 
 {"a": 1, "b": 2, "c": 3}
@@ -144,22 +144,24 @@ with 1) for too-long rows:
 mlr --icsv --ojson --allow-ragged-csv-input cat data/het/ragged.csv
 
+[
 {
   "a": 1,
   "b": 2,
   "c": 3
-}
+},
 {
   "a": 4,
   "b": 5,
   "c": ""
-}
+},
 {
   "a": 7,
   "b": 8,
   "c": 9,
   "4": 10
 }
+]
 
### Irregular data @@ -191,7 +193,7 @@ We can use the [`regularize`](reference-verbs.md#regularize) or the keys:
-mlr --json --no-jvstack regularize data/het/irregular.json
+mlr --jsonl regularize data/het/irregular.json
 
 {"a": 1, "b": 2, "c": 3}
@@ -213,21 +215,23 @@ data for items which are present, but won't log data for items which aren't.
 mlr --json cat data/het/sparse.json
 
+[
 {
   "host": "xy01.east",
   "status": "running",
   "volume": "/dev/sda1"
-}
+},
 {
   "host": "xy92.west",
   "status": "running"
-}
+},
 {
   "purpose": "failover",
   "host": "xy55.east",
   "volume": "/dev/sda1",
   "reimaged": true
 }
+]
 
This data is called **sparse** (from the [data-storage term](https://en.wikipedia.org/wiki/Sparse_matrix)). @@ -239,20 +243,21 @@ every record has the same keys: mlr --json unsparsify data/het/sparse.json
+[
 {
   "host": "xy01.east",
   "status": "running",
   "volume": "/dev/sda1",
   "purpose": "",
   "reimaged": ""
-}
+},
 {
   "host": "xy92.west",
   "status": "running",
   "volume": "",
   "purpose": "",
   "reimaged": ""
-}
+},
 {
   "host": "xy55.east",
   "status": "",
@@ -260,6 +265,7 @@ every record has the same keys:
   "purpose": "failover",
   "reimaged": true
 }
+]
 
Since this data is now homogeneous (rectangular), it pretty-prints nicely: diff --git a/docs/src/record-heterogeneity.md.in b/docs/src/record-heterogeneity.md.in index 989e92ad5..3b58b5cad 100644 --- a/docs/src/record-heterogeneity.md.in +++ b/docs/src/record-heterogeneity.md.in @@ -21,10 +21,10 @@ GENMD-RUN-COMMAND mlr --csv cat data/het/hom.csv GENMD-EOF -It has three records (written here using JSON formatting): +It has three records (written here using JSON Lines formatting): GENMD-RUN-COMMAND -mlr --icsv --ojson --no-jvstack cat data/het/hom.csv +mlr --icsv --ojsonl cat data/het/hom.csv GENMD-EOF Here every row has the same keys, in the same order: `a,b,c`. @@ -44,7 +44,7 @@ mlr --csv cat data/het/fillable.csv GENMD-EOF GENMD-RUN-COMMAND -mlr --icsv --ojson --no-jvstack cat data/het/fillable.csv +mlr --icsv --ojsonl cat data/het/fillable.csv GENMD-EOF This example is still homogeneous, though: every row has the same keys, in the same order: `a,b,c`. @@ -108,7 +108,7 @@ We can use the [`regularize`](reference-verbs.md#regularize) or the keys: GENMD-RUN-COMMAND -mlr --json --no-jvstack regularize data/het/irregular.json +mlr --jsonl regularize data/het/irregular.json GENMD-EOF The `regularize` verb tries to re-order subsequent rows to look like the first diff --git a/docs/src/reference-dsl-operators.md b/docs/src/reference-dsl-operators.md index 9690b18eb..50628c56c 100644 --- a/docs/src/reference-dsl-operators.md +++ b/docs/src/reference-dsl-operators.md @@ -106,6 +106,8 @@ However, in Miller 6 it has optional use for map traversal. Example:
 bar.baz
 bar.baz
+[
+]
 
This also works on the left-hand sides of assignment statements: @@ -116,6 +118,7 @@ This also works on the left-hand sides of assignment statements: '
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -137,6 +140,7 @@ This also works on the left-hand sides of assignment statements:
     }
   }
 }
+]
 
A few caveats: @@ -150,6 +154,8 @@ A few caveats:
 6989
+[
+]
 
* However (awkwardly), if you want to use `.` for map-traversal as well as string-concatenation in the same statement, you'll need to insert parentheses, as the default associativity is left-to-right: @@ -161,6 +167,8 @@ A few caveats:
 (error)
+[
+]
 
@@ -170,4 +178,6 @@ A few caveats:
 
 GET -- api/check
+[
+]
 
diff --git a/docs/src/reference-main-data-types.md b/docs/src/reference-main-data-types.md index a773a8c42..3c74f928b 100644 --- a/docs/src/reference-main-data-types.md +++ b/docs/src/reference-main-data-types.md @@ -155,27 +155,30 @@ id,blob mlr --icsv --ojson --from data/json-in-csv.csv cat
+[
 {
   "id": 100,
   "blob": "{\"a\":1,\"b\":[2,3,4]}"
-}
+},
 {
   "id": 105,
   "blob": "{\"a\":6,\"b\":[7,8,9]}"
 }
+]
 
 mlr --icsv --ojson --from data/json-in-csv.csv json-parse -f blob
 
+[
 {
   "id": 100,
   "blob": {
     "a": 1,
     "b": [2, 3, 4]
   }
-}
+},
 {
   "id": 105,
   "blob": {
@@ -183,19 +186,21 @@ id,blob
     "b": [7, 8, 9]
   }
 }
+]
 
 mlr --icsv --ojson --from data/json-in-csv.csv put '$blob = json_parse($blob)'
 
+[
 {
   "id": 100,
   "blob": {
     "a": 1,
     "b": [2, 3, 4]
   }
-}
+},
 {
   "id": 105,
   "blob": {
@@ -203,6 +208,7 @@ id,blob
     "b": [7, 8, 9]
   }
 }
+]
 
These have their respective operations to convert back to string: the diff --git a/docs/src/reference-main-flag-list.md b/docs/src/reference-main-flag-list.md index 3b03fd50e..710d48809 100644 --- a/docs/src/reference-main-flag-list.md +++ b/docs/src/reference-main-flag-list.md @@ -22,6 +22,7 @@ Here are flags you can use when invoking Miller. For example, when you type mlr --icsv --ojson head -n 1 example.csv
+[
 {
   "color": "yellow",
   "shape": "triangle",
@@ -31,6 +32,7 @@ Here are flags you can use when invoking Miller.  For example, when you type
   "quantity": 43.6498,
   "rate": 9.8870
 }
+]
 
the `--icsv` and `--ojson` bits are _flags_. See the [Miller command @@ -149,6 +151,7 @@ are overridden in all cases by setting output format to `format2`. * `--idkvp`: Use DKVP format for input data. * `--igen`: Ignore input files and instead generate sequential numeric input using --gen-field-name, --gen-start, --gen-step, and --gen-stop values. See also the seqgen verb, which is more useful/intuitive. * `--ijson`: Use JSON format for input data. +* `--ijsonl`: Use JSON Lines format for input data. * `--inidx`: Use NIDX format for input data. * `--io {format name}`: Use format name for input and output data. For example: `--io csv` is the same as `--csv`. * `--ipprint`: Use PPRINT format for input data. @@ -157,12 +160,14 @@ are overridden in all cases by setting output format to `format2`. * `--iusv or --iusvlite`: Use USV format for input data. * `--ixtab`: Use XTAB format for input data. * `--json or -j`: Use JSON format for input and output data. +* `--jsonl`: Use JSON Lines format for input and output data. * `--nidx`: Use NIDX format for input and output data. * `--oasv or --oasvlite`: Use ASV format for output data. * `--ocsv`: Use CSV format for output data. * `--ocsvlite`: Use CSV-lite format for output data. * `--odkvp`: Use DKVP format for output data. * `--ojson`: Use JSON format for output data. +* `--ojsonl`: Use JSON Lines format for output data. * `--omd`: Use markdown-tabular format for output data. * `--onidx`: Use NIDX format for output data. * `--opprint`: Use PPRINT format for output data. @@ -213,17 +218,6 @@ Additionally: * `-p` is a keystroke-saver for `--nidx --fs space --repifs`. * `-T` is a keystroke-saver for `--nidx --fs tab`. -## JSON-only flags - -These are flags which are applicable to JSON format. - - -**Flags:** - -* `--jlistwrap or --jl`: Wrap JSON output in outermost `[ ]`. -* `--jvstack`: Put one key-value pair per line for JSON output (multi-line output). -* `--no-jvstack`: Put objects/arrays all on one line for JSON output. - ## Legacy flags These are flags which don't do anything in the current Miller version. @@ -233,13 +227,17 @@ They are accepted as no-op flags in order to keep old scripts from breaking. **Flags:** * `--jknquoteint`: Type information from JSON input files is now preserved throughout the processing stream. +* `--jlistwrap or --jl`: Wrap JSON output in outermost `[ ]`. This is the default for JSON output format. * `--jquoteall`: Type information from JSON input files is now preserved throughout the processing stream. * `--json-fatal-arrays-on-input`: Miller now supports arrays as of version 6. * `--json-map-arrays-on-input`: Miller now supports arrays as of version 6. * `--json-skip-arrays-on-input`: Miller now supports arrays as of version 6. * `--jsonx`: The `--jvstack` flag is now default true in Miller 6. * `--jvquoteall`: Type information from JSON input files is now preserved throughout the processing stream. +* `--jvstack`: Put one key-value pair per line for JSON output (multi-line output). This is the default for JSON output format. * `--mmap`: Miller no longer uses memory-mapping to access data files. +* `--no-jlistwrap`: Wrap JSON output in outermost `[ ]`. This is the default for JSON Lines output format. +* `--no-jvstack`: Put objects/arrays all on one line for JSON output. This is the default for JSON Lines output format. * `--no-mmap`: Miller no longer uses memory-mapping to access data files. * `--ojsonx`: The `--jvstack` flag is now default true in Miller 6. * `--quote-all`: Ignored as of version 6. Types are inferred/retained through the processing flow now. diff --git a/docs/src/reference-verbs.md b/docs/src/reference-verbs.md index eecdc27e8..5d4c6da8d 100644 --- a/docs/src/reference-verbs.md +++ b/docs/src/reference-verbs.md @@ -366,72 +366,80 @@ leave off -k as well as -v. mlr --icsv --ojson cat data/clean-whitespace.csv
+[
 {
   "  Name  ": "  Ann  Simons",
   " Preference  ": "  blue  "
-}
+},
 {
   "  Name  ": "Bob Wang  ",
   " Preference  ": " red       "
-}
+},
 {
   "  Name  ": " Carol  Vee",
   " Preference  ": "    yellow"
 }
+]
 
 mlr --icsv --ojson clean-whitespace -k data/clean-whitespace.csv
 
+[
 {
   "Name": "  Ann  Simons",
   "Preference": "  blue  "
-}
+},
 {
   "Name": "Bob Wang  ",
   "Preference": " red       "
-}
+},
 {
   "Name": " Carol  Vee",
   "Preference": "    yellow"
 }
+]
 
 mlr --icsv --ojson clean-whitespace -v data/clean-whitespace.csv
 
+[
 {
   "  Name  ": "Ann Simons",
   " Preference  ": "blue"
-}
+},
 {
   "  Name  ": "Bob Wang",
   " Preference  ": "red"
-}
+},
 {
   "  Name  ": "Carol Vee",
   " Preference  ": "yellow"
 }
+]
 
 mlr --icsv --ojson clean-whitespace data/clean-whitespace.csv
 
+[
 {
   "Name": "Ann Simons",
   "Preference": "blue"
-}
+},
 {
   "Name": "Bob Wang",
   "Preference": "red"
-}
+},
 {
   "Name": "Carol Vee",
   "Preference": "yellow"
 }
+]
 
Function links: @@ -2941,21 +2949,23 @@ c b a mlr --json sort-within-records data/sort-within-records.json
+[
 {
   "a": 1,
   "b": 2,
   "c": 3
-}
+},
 {
   "a": 5,
   "b": 4,
   "c": 6
-}
+},
 {
   "a": 9,
   "b": 8,
   "c": 7
 }
+]
 
@@ -3874,6 +3884,7 @@ Examples:
 mlr --json unsparsify data/sparse.json
 
+[
 {
   "a": 1,
   "b": 2,
@@ -3881,7 +3892,7 @@ Examples:
   "u": "",
   "x": "",
   "w": ""
-}
+},
 {
   "a": "",
   "b": 2,
@@ -3889,7 +3900,7 @@ Examples:
   "u": 1,
   "x": "",
   "w": ""
-}
+},
 {
   "a": 1,
   "b": "",
@@ -3897,7 +3908,7 @@ Examples:
   "u": "",
   "x": 3,
   "w": ""
-}
+},
 {
   "a": "",
   "b": "",
@@ -3906,6 +3917,7 @@ Examples:
   "x": "",
   "w": 2
 }
+]
 
diff --git a/docs/src/repl.md b/docs/src/repl.md
index db1864b66..8a23605d0 100644
--- a/docs/src/repl.md
+++ b/docs/src/repl.md
@@ -66,6 +66,7 @@ Using `put` and `filter`, you can do the following as we've seen above:
 
 HELLO
+[
 {
   "color": "yellow",
   "shape": "triangle",
@@ -75,7 +76,7 @@ HELLO
   "quantity": 43.6498,
   "rate": 9.8870,
   "qr": 4.414868008496004
-}
+},
 {
   "color": "red",
   "shape": "square",
@@ -85,8 +86,9 @@ HELLO
   "quantity": 79.2778,
   "rate": 0.0130,
   "qr": 6098.292307692308
-}
-GOODBYE
+}GOODBYE
+
+]
 
## Using Miller with the REPL diff --git a/docs/src/scripting.md b/docs/src/scripting.md index 8757df9d5..aa67d8db0 100644 --- a/docs/src/scripting.md +++ b/docs/src/scripting.md @@ -88,37 +88,41 @@ circle 3 0.3 example-shell-script --ojson example.csv
+[
 {
   "shape": "triangle",
   "count": 3,
   "count_fraction": 0.3
-}
+},
 {
   "shape": "square",
   "count": 4,
   "count_fraction": 0.4
-}
+},
 {
   "shape": "circle",
   "count": 3,
   "count_fraction": 0.3
 }
+]
 
 example-shell-script --ojson then filter '$count == 3' example.csv
 
+[
 {
   "shape": "triangle",
   "count": 3,
   "count_fraction": 0.3
-}
+},
 {
   "shape": "circle",
   "count": 3,
   "count_fraction": 0.3
 }
+]
 
etc. @@ -172,37 +176,41 @@ circle 3 0.3 example-mlr-s-script --ojson example.csv
+[
 {
   "shape": "triangle",
   "count": 3,
   "count_fraction": 0.3
-}
+},
 {
   "shape": "square",
   "count": 4,
   "count_fraction": 0.4
-}
+},
 {
   "shape": "circle",
   "count": 3,
   "count_fraction": 0.3
 }
+]
 
 example-mlr-s-script --ojson then filter '$count == 3' example.csv
 
+[
 {
   "shape": "triangle",
   "count": 3,
   "count_fraction": 0.3
-}
+},
 {
   "shape": "circle",
   "count": 3,
   "count_fraction": 0.3
 }
+]
 
## Miller scripts on Windows @@ -245,37 +253,41 @@ circle 3 0.3 mlr -s example-mlr-s-script-no-shebang --ojson example.csv
+[
 {
   "shape": "triangle",
   "count": 3,
   "count_fraction": 0.3
-}
+},
 {
   "shape": "square",
   "count": 4,
   "count_fraction": 0.4
-}
+},
 {
   "shape": "circle",
   "count": 3,
   "count_fraction": 0.3
 }
+]
 
 mlr -s example-mlr-s-script-no-shebang --ojson then filter '$count == 3' example.csv
 
+[
 {
   "shape": "triangle",
   "count": 3,
   "count_fraction": 0.3
-}
+},
 {
   "shape": "circle",
   "count": 3,
   "count_fraction": 0.3
 }
+]
 
and so on. See also [Miller on Windows](miller-on-windows.md). diff --git a/docs/src/sorting.md b/docs/src/sorting.md index 0675d18be..73af42cb3 100644 --- a/docs/src/sorting.md +++ b/docs/src/sorting.md @@ -407,6 +407,7 @@ Also note that, unlike the `sort-within-record` verb with its `-r` flag, '
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -428,6 +429,7 @@ Also note that, unlike the `sort-within-record` verb with its `-r` flag,
     }
   }
 }
+]
 
## Simple sorting of maps across records @@ -529,6 +531,7 @@ recaptiulate (for reference) what `sort` with default flags already does; the th '
+[
 {
   "key": "alpha",
   "values": "5;2;8;6;1;4;9;10;3;7",
@@ -536,6 +539,7 @@ recaptiulate (for reference) what `sort` with default flags already does; the th
   "reverse": [10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
   "even_then_odd": [2, 4, 6, 8, 10, 1, 3, 5, 7, 9]
 }
+]
 
## Custom sorting of arrays across records diff --git a/docs/src/special-symbols-and-formatting.md b/docs/src/special-symbols-and-formatting.md index 02388f441..668b28930 100644 --- a/docs/src/special-symbols-and-formatting.md +++ b/docs/src/special-symbols-and-formatting.md @@ -35,14 +35,16 @@ Likewise [JSON](file-formats.md#json): mlr --icsv --ojson cat commas.csv
+[
 {
   "Name": "Xiao, Lin",
   "Role": "administrator"
-}
+},
 {
   "Name": "Khavari, Darius",
   "Role": "tester"
 }
+]
 
For Miller's [XTAB](file-formats.md#xtab-vertical-tabular) there is no escaping for carriage returns, but commas work fine: diff --git a/docs/src/sql-examples.md b/docs/src/sql-examples.md index 48e605cf0..781b0003a 100644 --- a/docs/src/sql-examples.md +++ b/docs/src/sql-examples.md @@ -54,50 +54,50 @@ last_update_time int(11) YES - NULL - Since Miller handles TSV output, we can do as much or as little processing as we want in the SQL query, then send the rest on to Miller. This includes outputting as JSON, doing further selects/joins in Miller, doing stats, etc. etc.:
-mysql --database=mydb -B -e 'show columns in mytable' | mlr --itsvlite --ojson --jlistwrap --jvstack cat
+mysql --database=mydb -B -e 'show columns in mytable' | mlr --itsvlite --ojson cat
 
 [
-  {
-    "Field": "id",
-    "Type": "bigint(20)",
-    "Null": "NO",
-    "Key": "MUL",
-    "Default": "NULL",
-    "Extra": ""
-  },
-  {
-    "Field": "category",
-    "Type": "varchar(256)",
-    "Null": "NO",
-    "Key": "",
-    "Default": "NULL",
-    "Extra": ""
-  },
-  {
-    "Field": "is_permanent",
-    "Type": "tinyint(1)",
-    "Null": "NO",
-    "Key": "",
-    "Default": "NULL",
-    "Extra": ""
-  },
-  {
-    "Field": "assigned_to",
-    "Type": "bigint(20)",
-    "Null": "YES",
-    "Key": "",
-    "Default": "NULL",
-    "Extra": ""
-  },
-  {
-    "Field": "last_update_time",
-    "Type": "int(11)",
-    "Null": "YES",
-    "Key": "",
-    "Default": "NULL",
-    "Extra": ""
-  }
+{
+  "Field": "id",
+  "Type": "bigint(20)",
+  "Null": "NO",
+  "Key": "MUL",
+  "Default": "NULL",
+  "Extra": ""
+},
+{
+  "Field": "category",
+  "Type": "varchar(256)",
+  "Null": "NO",
+  "Key": "",
+  "Default": "NULL",
+  "Extra": ""
+},
+{
+  "Field": "is_permanent",
+  "Type": "tinyint(1)",
+  "Null": "NO",
+  "Key": "",
+  "Default": "NULL",
+  "Extra": ""
+},
+{
+  "Field": "assigned_to",
+  "Type": "bigint(20)",
+  "Null": "YES",
+  "Key": "",
+  "Default": "NULL",
+  "Extra": ""
+},
+{
+  "Field": "last_update_time",
+  "Type": "int(11)",
+  "Null": "YES",
+  "Key": "",
+  "Default": "NULL",
+  "Extra": ""
+}
 ]
 
diff --git a/docs/src/sql-examples.md.in b/docs/src/sql-examples.md.in index 7555c7346..9c63fd576 100644 --- a/docs/src/sql-examples.md.in +++ b/docs/src/sql-examples.md.in @@ -34,48 +34,48 @@ GENMD-EOF Since Miller handles TSV output, we can do as much or as little processing as we want in the SQL query, then send the rest on to Miller. This includes outputting as JSON, doing further selects/joins in Miller, doing stats, etc. etc.: GENMD-CARDIFY-HIGHLIGHT-ONE -mysql --database=mydb -B -e 'show columns in mytable' | mlr --itsvlite --ojson --jlistwrap --jvstack cat +mysql --database=mydb -B -e 'show columns in mytable' | mlr --itsvlite --ojson cat [ - { - "Field": "id", - "Type": "bigint(20)", - "Null": "NO", - "Key": "MUL", - "Default": "NULL", - "Extra": "" - }, - { - "Field": "category", - "Type": "varchar(256)", - "Null": "NO", - "Key": "", - "Default": "NULL", - "Extra": "" - }, - { - "Field": "is_permanent", - "Type": "tinyint(1)", - "Null": "NO", - "Key": "", - "Default": "NULL", - "Extra": "" - }, - { - "Field": "assigned_to", - "Type": "bigint(20)", - "Null": "YES", - "Key": "", - "Default": "NULL", - "Extra": "" - }, - { - "Field": "last_update_time", - "Type": "int(11)", - "Null": "YES", - "Key": "", - "Default": "NULL", - "Extra": "" - } +{ + "Field": "id", + "Type": "bigint(20)", + "Null": "NO", + "Key": "MUL", + "Default": "NULL", + "Extra": "" +}, +{ + "Field": "category", + "Type": "varchar(256)", + "Null": "NO", + "Key": "", + "Default": "NULL", + "Extra": "" +}, +{ + "Field": "is_permanent", + "Type": "tinyint(1)", + "Null": "NO", + "Key": "", + "Default": "NULL", + "Extra": "" +}, +{ + "Field": "assigned_to", + "Type": "bigint(20)", + "Null": "YES", + "Key": "", + "Default": "NULL", + "Extra": "" +}, +{ + "Field": "last_update_time", + "Type": "int(11)", + "Null": "YES", + "Key": "", + "Default": "NULL", + "Extra": "" +} ] GENMD-EOF diff --git a/docs/src/two-pass-algorithms.md b/docs/src/two-pass-algorithms.md index bd8b9331a..146f3a81e 100644 --- a/docs/src/two-pass-algorithms.md +++ b/docs/src/two-pass-algorithms.md @@ -296,57 +296,59 @@ Then mlr --json put -q -f data/feature-count.mlr data/features.json
+[
 {
   "record_count": 12
-}
+},
 {
   "key": "qoh",
   "key_counts": 8
-}
+},
 {
   "key": "rate",
   "key_counts": 8
-}
+},
 {
   "key": "latency",
   "key_counts": 7
-}
+},
 {
   "key": "name",
   "key_counts": 4
-}
+},
 {
   "key": "uid",
   "key_counts": 3
-}
+},
 {
   "key": "uid2",
   "key_counts": 1
-}
+},
 {
   "key": "qoh",
   "key_fraction": 0.6666666666666666
-}
+},
 {
   "key": "rate",
   "key_fraction": 0.6666666666666666
-}
+},
 {
   "key": "latency",
   "key_fraction": 0.5833333333333334
-}
+},
 {
   "key": "name",
   "key_fraction": 0.3333333333333333
-}
+},
 {
   "key": "uid",
   "key_fraction": 0.25
-}
+},
 {
   "key": "uid2",
   "key_fraction": 0.08333333333333333
 }
+]
 
@@ -429,6 +431,7 @@ end {
 mlr --json put -q -f data/unsparsify.mlr data/sparse.json
 
+[
 {
   "a": 1,
   "b": 2,
@@ -436,7 +439,7 @@ end {
   "u": "",
   "x": "",
   "w": ""
-}
+},
 {
   "a": "",
   "b": 2,
@@ -444,7 +447,7 @@ end {
   "u": 1,
   "x": "",
   "w": ""
-}
+},
 {
   "a": 1,
   "b": "",
@@ -452,7 +455,7 @@ end {
   "u": "",
   "x": 3,
   "w": ""
-}
+},
 {
   "a": "",
   "b": "",
@@ -461,6 +464,7 @@ end {
   "x": "",
   "w": 2
 }
+]
 
diff --git a/internal/pkg/auxents/help/entry.go b/internal/pkg/auxents/help/entry.go
index e5d276068..8b362f4c7 100644
--- a/internal/pkg/auxents/help/entry.go
+++ b/internal/pkg/auxents/help/entry.go
@@ -354,22 +354,32 @@ TSV: same but with tabs in places of commas
 | 4,5,6               | Record 2: "apple":"4", "bat":"5", "cog":"6"
 +---------------------+
 
-JSON (sequence or array of objects):
+JSON (array of objects):
 +---------------------+
+| [                   |
 | {                   |
 |  "apple": 1,        | Record 1: "apple":"1", "bat":"2", "cog":"3"
 |  "bat": 2,          |
 |  "cog": 3           |
-| }                   |
+| },                  |
 | {                   |
-|   "dish": {         | Record 2: "dish:egg":"7",
-|     "egg": 7,       | "dish:flint":"8", "garlic":""
+|   "dish": {         | Record 2: "dish.egg":"7",
+|     "egg": 7,       | "dish.flint":"8", "garlic":""
 |     "flint": 8      |
 |   },                |
 |   "garlic": ""      |
 | }                   |
+| ]                   |
 +---------------------+
 
+JSON Lines (sequence of one-line objects):
++------------------------------------------------+
+| {"apple": 1, "bat": 2, "cog": 3}               |
+| {"dish": {"egg": 7, "flint": 8}, "garlic": ""} |
++------------------------------------------------+
+  Record 1: "apple":"1", "bat":"2", "cog":"3"
+  Record 2: "dish:egg":"7", "dish:flint":"8", "garlic":""
+
 PPRINT: pretty-printed tabular
 +---------------------+
 | apple bat cog       |
diff --git a/internal/pkg/cli/option_parse.go b/internal/pkg/cli/option_parse.go
index 551a80666..9c33aa2b0 100644
--- a/internal/pkg/cli/option_parse.go
+++ b/internal/pkg/cli/option_parse.go
@@ -91,7 +91,6 @@ var FLAG_TABLE = FlagTable{
 		&SeparatorFlagSection,
 		&FileFormatFlagSection,
 		&FormatConversionKeystrokeSaverFlagSection,
-		&JSONOnlyFlagSection,
 		&CSVOnlyFlagSection,
 		&PPRINTOnlyFlagSection,
 		&CompressedDataFlagSection,
@@ -407,50 +406,6 @@ var SeparatorFlagSection = FlagSection{
 	},
 }
 
-// ================================================================
-// JSON-ONLY FLAGS
-
-func JSONOnlyPrintInfo() {
-	fmt.Println("These are flags which are applicable to JSON format.")
-}
-
-func init() { JSONOnlyFlagSection.Sort() }
-
-var JSONOnlyFlagSection = FlagSection{
-	name:        "JSON-only flags",
-	infoPrinter: JSONOnlyPrintInfo,
-	flags: []Flag{
-
-		{
-			name: "--jvstack",
-			help: "Put one key-value pair per line for JSON output (multi-line output).",
-			parser: func(args []string, argc int, pargi *int, options *TOptions) {
-				options.WriterOptions.JSONOutputMultiline = true
-				*pargi += 1
-			},
-		},
-
-		{
-			name: "--no-jvstack",
-			help: "Put objects/arrays all on one line for JSON output.",
-			parser: func(args []string, argc int, pargi *int, options *TOptions) {
-				options.WriterOptions.JSONOutputMultiline = false
-				*pargi += 1
-			},
-		},
-
-		{
-			name:     "--jlistwrap",
-			altNames: []string{"--jl"},
-			help:     "Wrap JSON output in outermost `[ ]`.",
-			parser: func(args []string, argc int, pargi *int, options *TOptions) {
-				options.WriterOptions.WrapJSONOutputInOuterList = true
-				*pargi += 1
-			},
-		},
-	},
-}
-
 // ================================================================
 // PPRINT-ONLY FLAGS
 
@@ -590,6 +545,43 @@ var LegacyFlagSection = FlagSection{
 			help:   "Ignored as of version 6. Types are inferred/retained through the processing flow now.",
 			parser: NoOpParse1,
 		},
+
+		{
+			name: "--jvstack",
+			help: "Put one key-value pair per line for JSON output (multi-line output). This is the default for JSON output format.",
+			parser: func(args []string, argc int, pargi *int, options *TOptions) {
+				options.WriterOptions.JSONOutputMultiline = true
+				*pargi += 1
+			},
+		},
+
+		{
+			name: "--no-jvstack",
+			help: "Put objects/arrays all on one line for JSON output. This is the default for JSON Lines output format.",
+			parser: func(args []string, argc int, pargi *int, options *TOptions) {
+				options.WriterOptions.JSONOutputMultiline = false
+				*pargi += 1
+			},
+		},
+
+		{
+			name:     "--jlistwrap",
+			altNames: []string{"--jl"},
+			help:     "Wrap JSON output in outermost `[ ]`. This is the default for JSON output format.",
+			parser: func(args []string, argc int, pargi *int, options *TOptions) {
+				options.WriterOptions.WrapJSONOutputInOuterList = true
+				*pargi += 1
+			},
+		},
+
+		{
+			name: "--no-jlistwrap",
+			help: "Wrap JSON output in outermost `[ ]`. This is the default for JSON Lines output format.",
+			parser: func(args []string, argc int, pargi *int, options *TOptions) {
+				options.WriterOptions.WrapJSONOutputInOuterList = false
+				*pargi += 1
+			},
+		},
 	},
 }
 
@@ -700,6 +692,15 @@ var FileFormatFlagSection = FlagSection{
 			},
 		},
 
+		{
+			name: "--ijsonl",
+			help: "Use JSON Lines format for input data.",
+			parser: func(args []string, argc int, pargi *int, options *TOptions) {
+				options.ReaderOptions.InputFileFormat = "json"
+				*pargi += 1
+			},
+		},
+
 		{
 			name: "--inidx",
 			help: "Use NIDX format for input data.",
@@ -892,6 +893,19 @@ var FileFormatFlagSection = FlagSection{
 			help: "Use JSON format for output data.",
 			parser: func(args []string, argc int, pargi *int, options *TOptions) {
 				options.WriterOptions.OutputFileFormat = "json"
+				options.WriterOptions.WrapJSONOutputInOuterList = true
+				options.WriterOptions.JSONOutputMultiline = true
+				*pargi += 1
+			},
+		},
+
+		{
+			name: "--ojsonl",
+			help: "Use JSON Lines format for output data.",
+			parser: func(args []string, argc int, pargi *int, options *TOptions) {
+				options.WriterOptions.OutputFileFormat = "json"
+				options.WriterOptions.WrapJSONOutputInOuterList = false
+				options.WriterOptions.JSONOutputMultiline = false
 				*pargi += 1
 			},
 		},
@@ -1046,9 +1060,22 @@ var FileFormatFlagSection = FlagSection{
 			help:     "Use JSON format for input and output data.",
 			altNames: []string{"-j"},
 			parser: func(args []string, argc int, pargi *int, options *TOptions) {
-
 				options.ReaderOptions.InputFileFormat = "json"
 				options.WriterOptions.OutputFileFormat = "json"
+				options.WriterOptions.WrapJSONOutputInOuterList = true
+				options.WriterOptions.JSONOutputMultiline = true
+				*pargi += 1
+			},
+		},
+
+		{
+			name: "--jsonl",
+			help: "Use JSON Lines format for input and output data.",
+			parser: func(args []string, argc int, pargi *int, options *TOptions) {
+				options.ReaderOptions.InputFileFormat = "json"
+				options.WriterOptions.OutputFileFormat = "json"
+				options.WriterOptions.WrapJSONOutputInOuterList = false
+				options.WriterOptions.JSONOutputMultiline = false
 				*pargi += 1
 			},
 		},
@@ -1096,19 +1123,20 @@ var FileFormatFlagSection = FlagSection{
 
 func FormatConversionKeystrokeSaverPrintInfo() {
 	fmt.Println(`As keystroke-savers for format-conversion you may use the following.
-The letters c, t, j, d, n, x, p, and m refer to formats CSV, TSV, DKVP, NIDX,
-JSON, XTAB, PPRINT, and markdown, respectively. Note that markdown format is
-available for output only.
+The letters c, t, j, l, d, n, x, p, and m refer to formats CSV, TSV, DKVP, NIDX,
+JSON, JSON Lines, XTAB, PPRINT, and markdown, respectively. Note that markdown
+format is available for output only.
 
-| In\out | CSV   | TSV   | JSON   | DKVP   | NIDX   | XTAB   | PPRINT | Markdown |
+| In\out | CSV   | TSV   | JSON   | JSONL  | DKVP   | NIDX   | XTAB   | PPRINT | Markdown |
 +--------+-------+-------+--------+--------+--------+--------+--------+----------+
-| CSV    |       | --c2t | --c2j  | --c2d  | --c2n  | --c2x  | --c2p  | --c2m    |
-| TSV    | --t2c |       | --t2j  | --t2d  | --t2n  | --t2x  | --t2p  | --t2m    |
-| JSON   | --j2c | --j2t |        | --j2d  | --j2n  | --j2x  | --j2p  | --j2m    |
-| DKVP   | --d2c | --d2t | --d2j  |        | --d2n  | --d2x  | --d2p  | --d2m    |
-| NIDX   | --n2c | --n2t | --n2j  | --n2d  |        | --n2x  | --n2p  | --n2m    |
-| XTAB   | --x2c | --x2t | --x2j  | --x2d  | --x2n  |        | --x2p  | --x2m    |
-| PPRINT | --p2c | --p2t | --p2j  | --p2d  | --p2n  | --p2x  |        | --p2m    |`)
+| CSV    |       | --c2t | --c2j  | --c2l  | --c2d  | --c2n  | --c2x  | --c2p  | --c2m    |
+| TSV    | --t2c |       | --t2j  | --t2l  | --t2d  | --t2n  | --t2x  | --t2p  | --t2m    |
+| JSON   | --j2c | --j2t |        | --j2l  | --j2d  | --j2n  | --j2x  | --j2p  | --j2m    |
+| JSONL  | --l2c | --l2t |        |        | --l2d  | --l2n  | --l2x  | --l2p  | --l2m    |
+| DKVP   | --d2c | --d2t | --d2j  | --d2l  |        | --d2n  | --d2x  | --d2p  | --d2m    |
+| NIDX   | --n2c | --n2t | --n2j  | --n2l  | --n2d  |        | --n2x  | --n2p  | --n2m    |
+| XTAB   | --x2c | --x2t | --x2j  | --x2l  | --x2d  | --x2n  |        | --x2p  | --x2m    |
+| PPRINT | --p2c | --p2t | --p2j  | --p2l  | --p2d  | --p2n  | --p2x  |        | --p2m    |`)
 }
 
 func init() { FormatConversionKeystrokeSaverFlagSection.Sort() }
@@ -1202,6 +1230,23 @@ var FormatConversionKeystrokeSaverFlagSection = FlagSection{
 			parser: func(args []string, argc int, pargi *int, options *TOptions) {
 				options.ReaderOptions.InputFileFormat = "csv"
 				options.WriterOptions.OutputFileFormat = "json"
+				options.WriterOptions.WrapJSONOutputInOuterList = true
+				options.WriterOptions.JSONOutputMultiline = true
+				options.ReaderOptions.irsWasSpecified = true
+				*pargi += 1
+			},
+		},
+		{
+			name: "--c2l",
+			help: "Use CSV for input, JSON Lines for output.",
+			// For format-conversion keystroke-savers, a matrix is plenty -- we don't
+			// need to print a tedious 60-line list.
+			suppressFlagEnumeration: true,
+			parser: func(args []string, argc int, pargi *int, options *TOptions) {
+				options.ReaderOptions.InputFileFormat = "csv"
+				options.WriterOptions.OutputFileFormat = "json"
+				options.WriterOptions.WrapJSONOutputInOuterList = false
+				options.WriterOptions.JSONOutputMultiline = false
 				options.ReaderOptions.irsWasSpecified = true
 				*pargi += 1
 			},
@@ -1318,6 +1363,25 @@ var FormatConversionKeystrokeSaverFlagSection = FlagSection{
 				options.ReaderOptions.InputFileFormat = "csv"
 				options.ReaderOptions.IFS = "\t"
 				options.WriterOptions.OutputFileFormat = "json"
+				options.WriterOptions.WrapJSONOutputInOuterList = true
+				options.WriterOptions.JSONOutputMultiline = true
+				options.ReaderOptions.ifsWasSpecified = true
+				options.ReaderOptions.irsWasSpecified = true
+				*pargi += 1
+			},
+		},
+		{
+			name: "--t2l",
+			help: "Use TSV for input, JSON Lines for output.",
+			// For format-conversion keystroke-savers, a matrix is plenty -- we don't
+			// need to print a tedious 60-line list.
+			suppressFlagEnumeration: true,
+			parser: func(args []string, argc int, pargi *int, options *TOptions) {
+				options.ReaderOptions.InputFileFormat = "csv"
+				options.ReaderOptions.IFS = "\t"
+				options.WriterOptions.OutputFileFormat = "json"
+				options.WriterOptions.WrapJSONOutputInOuterList = false
+				options.WriterOptions.JSONOutputMultiline = false
 				options.ReaderOptions.ifsWasSpecified = true
 				options.ReaderOptions.irsWasSpecified = true
 				*pargi += 1
@@ -1435,6 +1499,22 @@ var FormatConversionKeystrokeSaverFlagSection = FlagSection{
 			parser: func(args []string, argc int, pargi *int, options *TOptions) {
 				options.ReaderOptions.InputFileFormat = "dkvp"
 				options.WriterOptions.OutputFileFormat = "json"
+				options.WriterOptions.WrapJSONOutputInOuterList = true
+				options.WriterOptions.JSONOutputMultiline = true
+				*pargi += 1
+			},
+		},
+		{
+			name: "--d2l",
+			help: "Use DKVP for input, JSON Lines for output.",
+			// For format-conversion keystroke-savers, a matrix is plenty -- we don't
+			// need to print a tedious 60-line list.
+			suppressFlagEnumeration: true,
+			parser: func(args []string, argc int, pargi *int, options *TOptions) {
+				options.ReaderOptions.InputFileFormat = "dkvp"
+				options.WriterOptions.OutputFileFormat = "json"
+				options.WriterOptions.WrapJSONOutputInOuterList = false
+				options.WriterOptions.JSONOutputMultiline = false
 				*pargi += 1
 			},
 		},
@@ -1537,6 +1617,22 @@ var FormatConversionKeystrokeSaverFlagSection = FlagSection{
 			parser: func(args []string, argc int, pargi *int, options *TOptions) {
 				options.ReaderOptions.InputFileFormat = "nidx"
 				options.WriterOptions.OutputFileFormat = "json"
+				options.WriterOptions.WrapJSONOutputInOuterList = true
+				options.WriterOptions.JSONOutputMultiline = true
+				*pargi += 1
+			},
+		},
+		{
+			name: "--n2l",
+			help: "Use NIDX for input, JSON Lines for output.",
+			// For format-conversion keystroke-savers, a matrix is plenty -- we don't
+			// need to print a tedious 60-line list.
+			suppressFlagEnumeration: true,
+			parser: func(args []string, argc int, pargi *int, options *TOptions) {
+				options.ReaderOptions.InputFileFormat = "nidx"
+				options.WriterOptions.OutputFileFormat = "json"
+				options.WriterOptions.WrapJSONOutputInOuterList = false
+				options.WriterOptions.JSONOutputMultiline = false
 				*pargi += 1
 			},
 		},
@@ -1692,6 +1788,108 @@ var FormatConversionKeystrokeSaverFlagSection = FlagSection{
 			},
 		},
 
+		{
+			name: "--l2c",
+			help: "Use JSON Lines for input, CSV for output.",
+			// For format-conversion keystroke-savers, a matrix is plenty -- we don't
+			// need to print a tedious 60-line list.
+			suppressFlagEnumeration: true,
+			parser: func(args []string, argc int, pargi *int, options *TOptions) {
+				options.ReaderOptions.InputFileFormat = "json"
+				options.WriterOptions.OutputFileFormat = "csv"
+				options.WriterOptions.orsWasSpecified = true
+				*pargi += 1
+			},
+		},
+		{
+			name: "--l2t",
+			help: "Use JSON Lines for input, TSV for output.",
+			// For format-conversion keystroke-savers, a matrix is plenty -- we don't
+			// need to print a tedious 60-line list.
+			suppressFlagEnumeration: true,
+			parser: func(args []string, argc int, pargi *int, options *TOptions) {
+				options.ReaderOptions.InputFileFormat = "json"
+				options.WriterOptions.OutputFileFormat = "csv"
+				options.WriterOptions.OFS = "\t"
+				options.WriterOptions.ofsWasSpecified = true
+				options.WriterOptions.orsWasSpecified = true
+				*pargi += 1
+			},
+		},
+		{
+			name: "--l2d",
+			help: "Use JSON Lines for input, DKVP for output.",
+			// For format-conversion keystroke-savers, a matrix is plenty -- we don't
+			// need to print a tedious 60-line list.
+			suppressFlagEnumeration: true,
+			parser: func(args []string, argc int, pargi *int, options *TOptions) {
+				options.ReaderOptions.InputFileFormat = "json"
+				options.WriterOptions.OutputFileFormat = "dkvp"
+				*pargi += 1
+			},
+		},
+		{
+			name: "--l2n",
+			help: "Use JSON Lines for input, NIDX for output.",
+			// For format-conversion keystroke-savers, a matrix is plenty -- we don't
+			// need to print a tedious 60-line list.
+			suppressFlagEnumeration: true,
+			parser: func(args []string, argc int, pargi *int, options *TOptions) {
+				options.ReaderOptions.InputFileFormat = "json"
+				options.WriterOptions.OutputFileFormat = "nidx"
+				*pargi += 1
+			},
+		},
+		{
+			name: "--l2p",
+			help: "Use JSON Lines for input, PPRINT for output.",
+			// For format-conversion keystroke-savers, a matrix is plenty -- we don't
+			// need to print a tedious 60-line list.
+			suppressFlagEnumeration: true,
+			parser: func(args []string, argc int, pargi *int, options *TOptions) {
+				options.ReaderOptions.InputFileFormat = "json"
+				options.WriterOptions.OutputFileFormat = "pprint"
+				*pargi += 1
+			},
+		},
+		{
+			name: "--l2b",
+			help: "Use JSON Lines for input, PPRINT with --barred for output.",
+			// For format-conversion keystroke-savers, a matrix is plenty -- we don't
+			// need to print a tedious 60-line list.
+			suppressFlagEnumeration: true,
+			parser: func(args []string, argc int, pargi *int, options *TOptions) {
+				options.ReaderOptions.InputFileFormat = "json"
+				options.WriterOptions.OutputFileFormat = "pprint"
+				options.WriterOptions.BarredPprintOutput = true
+				*pargi += 1
+			},
+		},
+		{
+			name: "--l2x",
+			help: "Use JSON Lines for input, XTAB for output.",
+			// For format-conversion keystroke-savers, a matrix is plenty -- we don't
+			// need to print a tedious 60-line list.
+			suppressFlagEnumeration: true,
+			parser: func(args []string, argc int, pargi *int, options *TOptions) {
+				options.ReaderOptions.InputFileFormat = "json"
+				options.WriterOptions.OutputFileFormat = "xtab"
+				*pargi += 1
+			},
+		},
+		{
+			name: "--l2m",
+			help: "Use JSON Lines for input, markdown-tabular for output.",
+			// For format-conversion keystroke-savers, a matrix is plenty -- we don't
+			// need to print a tedious 60-line list.
+			suppressFlagEnumeration: true,
+			parser: func(args []string, argc int, pargi *int, options *TOptions) {
+				options.ReaderOptions.InputFileFormat = "json"
+				options.WriterOptions.OutputFileFormat = "markdown"
+				*pargi += 1
+			},
+		},
+
 		{
 			name: "--p2c",
 			help: "Use PPRINT for input, CSV for output.",
@@ -1762,6 +1960,24 @@ var FormatConversionKeystrokeSaverFlagSection = FlagSection{
 				options.ReaderOptions.InputFileFormat = "pprint"
 				options.ReaderOptions.IFS = " "
 				options.WriterOptions.OutputFileFormat = "json"
+				options.WriterOptions.WrapJSONOutputInOuterList = true
+				options.WriterOptions.JSONOutputMultiline = true
+				options.ReaderOptions.ifsWasSpecified = true
+				*pargi += 1
+			},
+		},
+		{
+			name: "--p2l",
+			help: "Use PPRINT for input, JSON Lines for output.",
+			// For format-conversion keystroke-savers, a matrix is plenty -- we don't
+			// need to print a tedious 60-line list.
+			suppressFlagEnumeration: true,
+			parser: func(args []string, argc int, pargi *int, options *TOptions) {
+				options.ReaderOptions.InputFileFormat = "pprint"
+				options.ReaderOptions.IFS = " "
+				options.WriterOptions.OutputFileFormat = "json"
+				options.WriterOptions.WrapJSONOutputInOuterList = false
+				options.WriterOptions.JSONOutputMultiline = false
 				options.ReaderOptions.ifsWasSpecified = true
 				*pargi += 1
 			},
@@ -1856,6 +2072,22 @@ var FormatConversionKeystrokeSaverFlagSection = FlagSection{
 			parser: func(args []string, argc int, pargi *int, options *TOptions) {
 				options.ReaderOptions.InputFileFormat = "xtab"
 				options.WriterOptions.OutputFileFormat = "json"
+				options.WriterOptions.WrapJSONOutputInOuterList = true
+				options.WriterOptions.JSONOutputMultiline = true
+				*pargi += 1
+			},
+		},
+		{
+			name: "--x2l",
+			help: "Use XTAB for input, JSON Lines for output.",
+			// For format-conversion keystroke-savers, a matrix is plenty -- we don't
+			// need to print a tedious 60-line list.
+			suppressFlagEnumeration: true,
+			parser: func(args []string, argc int, pargi *int, options *TOptions) {
+				options.ReaderOptions.InputFileFormat = "xtab"
+				options.WriterOptions.OutputFileFormat = "json"
+				options.WriterOptions.WrapJSONOutputInOuterList = false
+				options.WriterOptions.JSONOutputMultiline = false
 				*pargi += 1
 			},
 		},
diff --git a/internal/pkg/cli/option_types.go b/internal/pkg/cli/option_types.go
index 7b366a5cd..5cd15ede7 100644
--- a/internal/pkg/cli/option_types.go
+++ b/internal/pkg/cli/option_types.go
@@ -98,8 +98,11 @@ type TWriterOptions struct {
 	RightAlignedPPRINTOutput bool
 	RightAlignedXTABOutput   bool
 
-	WrapJSONOutputInOuterList bool
-	JSONOutputMultiline       bool // Not using miller/types enum to avoid package cycle
+	// JSON output: --jlistwrap on, --jvstack on
+	// JSON Lines output: --jlistwrap off, --jvstack off
+	WrapJSONOutputInOuterList bool // --jlistwrap
+	JSONOutputMultiline       bool // --jvstack
+	// Not using miller/types enum to avoid package cycle
 
 	// When we read things like
 	//
@@ -202,11 +205,14 @@ func DefaultWriterOptions() TWriterOptions {
 		FLATSEP:            ".",
 		FlushOnEveryRecord: true,
 
-		HeaderlessCSVOutput:       false,
-		WrapJSONOutputInOuterList: false,
+		HeaderlessCSVOutput: false,
+
+		WrapJSONOutputInOuterList: true,
 		JSONOutputMultiline:       true,
-		AutoUnflatten:             true,
-		AutoFlatten:               true,
-		FPOFMT:                    "",
+
+		AutoUnflatten: true,
+		AutoFlatten:   true,
+
+		FPOFMT: "",
 	}
 }
diff --git a/man/manpage.txt b/man/manpage.txt
index 8da5f15af..ce925ef04 100644
--- a/man/manpage.txt
+++ b/man/manpage.txt
@@ -49,22 +49,32 @@ FILE FORMATS
        | 4,5,6               | Record 2: "apple":"4", "bat":"5", "cog":"6"
        +---------------------+
 
-       JSON (sequence or array of objects):
+       JSON (array of objects):
        +---------------------+
+       | [                   |
        | {                   |
        |  "apple": 1,        | Record 1: "apple":"1", "bat":"2", "cog":"3"
        |  "bat": 2,          |
        |  "cog": 3           |
-       | }                   |
+       | },                  |
        | {                   |
-       |   "dish": {         | Record 2: "dish:egg":"7",
-       |     "egg": 7,       | "dish:flint":"8", "garlic":""
+       |   "dish": {         | Record 2: "dish.egg":"7",
+       |     "egg": 7,       | "dish.flint":"8", "garlic":""
        |     "flint": 8      |
        |   },                |
        |   "garlic": ""      |
        | }                   |
+       | ]                   |
        +---------------------+
 
+       JSON Lines (sequence of one-line objects):
+       +------------------------------------------------+
+       | {"apple": 1, "bat": 2, "cog": 3}               |
+       | {"dish": {"egg": 7, "flint": 8}, "garlic": ""} |
+       +------------------------------------------------+
+         Record 1: "apple":"1", "bat":"2", "cog":"3"
+         Record 2: "dish:egg":"7", "dish:flint":"8", "garlic":""
+
        PPRINT: pretty-printed tabular
        +---------------------+
        | apple bat cog       |
@@ -118,7 +128,6 @@ HELP OPTIONS
          mlr help file-format-flags
          mlr help flatten-unflatten-flags
          mlr help format-conversion-keystroke-saver-flags
-         mlr help json-only-flags
          mlr help legacy-flags
          mlr help miscellaneous-flags
          mlr help output-colorization-flags
@@ -329,6 +338,7 @@ FILE-FORMAT FLAGS
                                 --gen-step, and --gen-stop values. See also the
                                 seqgen verb, which is more useful/intuitive.
        --ijson                  Use JSON format for input data.
+       --ijsonl                 Use JSON Lines format for input data.
        --inidx                  Use NIDX format for input data.
        --io {format name}       Use format name for input and output data. For
                                 example: `--io csv` is the same as `--csv`.
@@ -338,12 +348,14 @@ FILE-FORMAT FLAGS
        --iusv or --iusvlite     Use USV format for input data.
        --ixtab                  Use XTAB format for input data.
        --json or -j             Use JSON format for input and output data.
+       --jsonl                  Use JSON Lines format for input and output data.
        --nidx                   Use NIDX format for input and output data.
        --oasv or --oasvlite     Use ASV format for output data.
        --ocsv                   Use CSV format for output data.
        --ocsvlite               Use CSV-lite format for output data.
        --odkvp                  Use DKVP format for output data.
        --ojson                  Use JSON format for output data.
+       --ojsonl                 Use JSON Lines format for output data.
        --omd                    Use markdown-tabular format for output data.
        --onidx                  Use NIDX format for output data.
        --opprint                Use PPRINT format for output data.
@@ -385,37 +397,32 @@ FLATTEN-UNFLATTEN FLAGS
 
 FORMAT-CONVERSION KEYSTROKE-SAVER FLAGS
        As keystroke-savers for format-conversion you may use the following.
-       The letters c, t, j, d, n, x, p, and m refer to formats CSV, TSV, DKVP, NIDX,
-       JSON, XTAB, PPRINT, and markdown, respectively. Note that markdown format is
-       available for output only.
+       The letters c, t, j, l, d, n, x, p, and m refer to formats CSV, TSV, DKVP, NIDX,
+       JSON, JSON Lines, XTAB, PPRINT, and markdown, respectively. Note that markdown
+       format is available for output only.
 
-       | In\out | CSV   | TSV   | JSON   | DKVP   | NIDX   | XTAB   | PPRINT | Markdown |
+       | In\out | CSV   | TSV   | JSON   | JSONL  | DKVP   | NIDX   | XTAB   | PPRINT | Markdown |
        +--------+-------+-------+--------+--------+--------+--------+--------+----------+
-       | CSV    |       | --c2t | --c2j  | --c2d  | --c2n  | --c2x  | --c2p  | --c2m    |
-       | TSV    | --t2c |       | --t2j  | --t2d  | --t2n  | --t2x  | --t2p  | --t2m    |
-       | JSON   | --j2c | --j2t |        | --j2d  | --j2n  | --j2x  | --j2p  | --j2m    |
-       | DKVP   | --d2c | --d2t | --d2j  |        | --d2n  | --d2x  | --d2p  | --d2m    |
-       | NIDX   | --n2c | --n2t | --n2j  | --n2d  |        | --n2x  | --n2p  | --n2m    |
-       | XTAB   | --x2c | --x2t | --x2j  | --x2d  | --x2n  |        | --x2p  | --x2m    |
-       | PPRINT | --p2c | --p2t | --p2j  | --p2d  | --p2n  | --p2x  |        | --p2m    |
+       | CSV    |       | --c2t | --c2j  | --c2l  | --c2d  | --c2n  | --c2x  | --c2p  | --c2m    |
+       | TSV    | --t2c |       | --t2j  | --t2l  | --t2d  | --t2n  | --t2x  | --t2p  | --t2m    |
+       | JSON   | --j2c | --j2t |        | --j2l  | --j2d  | --j2n  | --j2x  | --j2p  | --j2m    |
+       | JSONL  | --l2c | --l2t |        |        | --l2d  | --l2n  | --l2x  | --l2p  | --l2m    |
+       | DKVP   | --d2c | --d2t | --d2j  | --d2l  |        | --d2n  | --d2x  | --d2p  | --d2m    |
+       | NIDX   | --n2c | --n2t | --n2j  | --n2l  | --n2d  |        | --n2x  | --n2p  | --n2m    |
+       | XTAB   | --x2c | --x2t | --x2j  | --x2l  | --x2d  | --x2n  |        | --x2p  | --x2m    |
+       | PPRINT | --p2c | --p2t | --p2j  | --p2l  | --p2d  | --p2n  | --p2x  |        | --p2m    |
 
        -p                       Keystroke-saver for `--nidx --fs space --repifs`.
        -T                       Keystroke-saver for `--nidx --fs tab`.
 
-JSON-ONLY FLAGS
-       These are flags which are applicable to JSON format.
-
-       --jlistwrap or --jl      Wrap JSON output in outermost `[ ]`.
-       --jvstack                Put one key-value pair per line for JSON output
-                                (multi-line output).
-       --no-jvstack             Put objects/arrays all on one line for JSON output.
-
 LEGACY FLAGS
        These are flags which don't do anything in the current Miller version.
        They are accepted as no-op flags in order to keep old scripts from breaking.
 
        --jknquoteint            Type information from JSON input files is now
                                 preserved throughout the processing stream.
+       --jlistwrap or --jl      Wrap JSON output in outermost `[ ]`. This is the
+                                default for JSON output format.
        --jquoteall              Type information from JSON input files is now
                                 preserved throughout the processing stream.
        --json-fatal-arrays-on-input
@@ -427,8 +434,15 @@ LEGACY FLAGS
        --jsonx                  The `--jvstack` flag is now default true in Miller 6.
        --jvquoteall             Type information from JSON input files is now
                                 preserved throughout the processing stream.
+       --jvstack                Put one key-value pair per line for JSON output
+                                (multi-line output). This is the default for JSON
+                                output format.
        --mmap                   Miller no longer uses memory-mapping to access data
                                 files.
+       --no-jlistwrap           Wrap JSON output in outermost `[ ]`. This is the
+                                default for JSON Lines output format.
+       --no-jvstack             Put objects/arrays all on one line for JSON output.
+                                This is the default for JSON Lines output format.
        --no-mmap                Miller no longer uses memory-mapping to access data
                                 files.
        --ojsonx                 The `--jvstack` flag is now default true in Miller 6.
@@ -3019,4 +3033,4 @@ SEE ALSO
 
 
 
-                                  2022-01-08                         MILLER(1)
+                                  2022-01-09                         MILLER(1)
diff --git a/man/mlr.1 b/man/mlr.1
index 8970bad16..c103c459a 100644
--- a/man/mlr.1
+++ b/man/mlr.1
@@ -2,12 +2,12 @@
 .\"     Title: mlr
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: ./mkman.rb
-.\"      Date: 2022-01-08
+.\"      Date: 2022-01-09
 .\"    Manual: \ \&
 .\"    Source: \ \&
 .\"  Language: English
 .\"
-.TH "MILLER" "1" "2022-01-08" "\ \&" "\ \&"
+.TH "MILLER" "1" "2022-01-09" "\ \&" "\ \&"
 .\" -----------------------------------------------------------------
 .\" * Portability definitions
 .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -78,22 +78,32 @@ TSV: same but with tabs in places of commas
 | 4,5,6               | Record 2: "apple":"4", "bat":"5", "cog":"6"
 +---------------------+
 
-JSON (sequence or array of objects):
+JSON (array of objects):
 +---------------------+
+| [                   |
 | {                   |
 |  "apple": 1,        | Record 1: "apple":"1", "bat":"2", "cog":"3"
 |  "bat": 2,          |
 |  "cog": 3           |
-| }                   |
+| },                  |
 | {                   |
-|   "dish": {         | Record 2: "dish:egg":"7",
-|     "egg": 7,       | "dish:flint":"8", "garlic":""
+|   "dish": {         | Record 2: "dish.egg":"7",
+|     "egg": 7,       | "dish.flint":"8", "garlic":""
 |     "flint": 8      |
 |   },                |
 |   "garlic": ""      |
 | }                   |
+| ]                   |
 +---------------------+
 
+JSON Lines (sequence of one-line objects):
++------------------------------------------------+
+| {"apple": 1, "bat": 2, "cog": 3}               |
+| {"dish": {"egg": 7, "flint": 8}, "garlic": ""} |
++------------------------------------------------+
+  Record 1: "apple":"1", "bat":"2", "cog":"3"
+  Record 2: "dish:egg":"7", "dish:flint":"8", "garlic":""
+
 PPRINT: pretty-printed tabular
 +---------------------+
 | apple bat cog       |
@@ -153,7 +163,6 @@ Flags:
   mlr help file-format-flags
   mlr help flatten-unflatten-flags
   mlr help format-conversion-keystroke-saver-flags
-  mlr help json-only-flags
   mlr help legacy-flags
   mlr help miscellaneous-flags
   mlr help output-colorization-flags
@@ -408,6 +417,7 @@ are overridden in all cases by setting output format to `format2`.
                          --gen-step, and --gen-stop values. See also the
                          seqgen verb, which is more useful/intuitive.
 --ijson                  Use JSON format for input data.
+--ijsonl                 Use JSON Lines format for input data.
 --inidx                  Use NIDX format for input data.
 --io {format name}       Use format name for input and output data. For
                          example: `--io csv` is the same as `--csv`.
@@ -417,12 +427,14 @@ are overridden in all cases by setting output format to `format2`.
 --iusv or --iusvlite     Use USV format for input data.
 --ixtab                  Use XTAB format for input data.
 --json or -j             Use JSON format for input and output data.
+--jsonl                  Use JSON Lines format for input and output data.
 --nidx                   Use NIDX format for input and output data.
 --oasv or --oasvlite     Use ASV format for output data.
 --ocsv                   Use CSV format for output data.
 --ocsvlite               Use CSV-lite format for output data.
 --odkvp                  Use DKVP format for output data.
 --ojson                  Use JSON format for output data.
+--ojsonl                 Use JSON Lines format for output data.
 --omd                    Use markdown-tabular format for output data.
 --onidx                  Use NIDX format for output data.
 --opprint                Use PPRINT format for output data.
@@ -480,41 +492,26 @@ See the Flatten/unflatten doc page for more information.
 .\}
 .nf
 As keystroke-savers for format-conversion you may use the following.
-The letters c, t, j, d, n, x, p, and m refer to formats CSV, TSV, DKVP, NIDX,
-JSON, XTAB, PPRINT, and markdown, respectively. Note that markdown format is
-available for output only.
+The letters c, t, j, l, d, n, x, p, and m refer to formats CSV, TSV, DKVP, NIDX,
+JSON, JSON Lines, XTAB, PPRINT, and markdown, respectively. Note that markdown
+format is available for output only.
 
-| In\eout | CSV   | TSV   | JSON   | DKVP   | NIDX   | XTAB   | PPRINT | Markdown |
+| In\eout | CSV   | TSV   | JSON   | JSONL  | DKVP   | NIDX   | XTAB   | PPRINT | Markdown |
 +--------+-------+-------+--------+--------+--------+--------+--------+----------+
-| CSV    |       | --c2t | --c2j  | --c2d  | --c2n  | --c2x  | --c2p  | --c2m    |
-| TSV    | --t2c |       | --t2j  | --t2d  | --t2n  | --t2x  | --t2p  | --t2m    |
-| JSON   | --j2c | --j2t |        | --j2d  | --j2n  | --j2x  | --j2p  | --j2m    |
-| DKVP   | --d2c | --d2t | --d2j  |        | --d2n  | --d2x  | --d2p  | --d2m    |
-| NIDX   | --n2c | --n2t | --n2j  | --n2d  |        | --n2x  | --n2p  | --n2m    |
-| XTAB   | --x2c | --x2t | --x2j  | --x2d  | --x2n  |        | --x2p  | --x2m    |
-| PPRINT | --p2c | --p2t | --p2j  | --p2d  | --p2n  | --p2x  |        | --p2m    |
+| CSV    |       | --c2t | --c2j  | --c2l  | --c2d  | --c2n  | --c2x  | --c2p  | --c2m    |
+| TSV    | --t2c |       | --t2j  | --t2l  | --t2d  | --t2n  | --t2x  | --t2p  | --t2m    |
+| JSON   | --j2c | --j2t |        | --j2l  | --j2d  | --j2n  | --j2x  | --j2p  | --j2m    |
+| JSONL  | --l2c | --l2t |        |        | --l2d  | --l2n  | --l2x  | --l2p  | --l2m    |
+| DKVP   | --d2c | --d2t | --d2j  | --d2l  |        | --d2n  | --d2x  | --d2p  | --d2m    |
+| NIDX   | --n2c | --n2t | --n2j  | --n2l  | --n2d  |        | --n2x  | --n2p  | --n2m    |
+| XTAB   | --x2c | --x2t | --x2j  | --x2l  | --x2d  | --x2n  |        | --x2p  | --x2m    |
+| PPRINT | --p2c | --p2t | --p2j  | --p2l  | --p2d  | --p2n  | --p2x  |        | --p2m    |
 
 -p                       Keystroke-saver for `--nidx --fs space --repifs`.
 -T                       Keystroke-saver for `--nidx --fs tab`.
 .fi
 .if n \{\
 .RE
-.SH "JSON-ONLY FLAGS"
-.sp
-
-.if n \{\
-.RS 0
-.\}
-.nf
-These are flags which are applicable to JSON format.
-
---jlistwrap or --jl      Wrap JSON output in outermost `[ ]`.
---jvstack                Put one key-value pair per line for JSON output
-                         (multi-line output).
---no-jvstack             Put objects/arrays all on one line for JSON output.
-.fi
-.if n \{\
-.RE
 .SH "LEGACY FLAGS"
 .sp
 
@@ -527,6 +524,8 @@ They are accepted as no-op flags in order to keep old scripts from breaking.
 
 --jknquoteint            Type information from JSON input files is now
                          preserved throughout the processing stream.
+--jlistwrap or --jl      Wrap JSON output in outermost `[ ]`. This is the
+                         default for JSON output format.
 --jquoteall              Type information from JSON input files is now
                          preserved throughout the processing stream.
 --json-fatal-arrays-on-input
@@ -538,8 +537,15 @@ They are accepted as no-op flags in order to keep old scripts from breaking.
 --jsonx                  The `--jvstack` flag is now default true in Miller 6.
 --jvquoteall             Type information from JSON input files is now
                          preserved throughout the processing stream.
+--jvstack                Put one key-value pair per line for JSON output
+                         (multi-line output). This is the default for JSON
+                         output format.
 --mmap                   Miller no longer uses memory-mapping to access data
                          files.
+--no-jlistwrap           Wrap JSON output in outermost `[ ]`. This is the
+                         default for JSON Lines output format.
+--no-jvstack             Put objects/arrays all on one line for JSON output.
+                         This is the default for JSON Lines output format.
 --no-mmap                Miller no longer uses memory-mapping to access data
                          files.
 --ojsonx                 The `--jvstack` flag is now default true in Miller 6.
diff --git a/test/cases/dsl-array-map-indexing/0010/expout b/test/cases/dsl-array-map-indexing/0010/expout
index 24c945fbd..444ec4530 100644
--- a/test/cases/dsl-array-map-indexing/0010/expout
+++ b/test/cases/dsl-array-map-indexing/0010/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -16,3 +17,4 @@
   },
   "z": (error)
 }
+]
diff --git a/test/cases/dsl-array-map-indexing/0011/expout b/test/cases/dsl-array-map-indexing/0011/expout
index 4f60fada6..cae49c68f 100644
--- a/test/cases/dsl-array-map-indexing/0011/expout
+++ b/test/cases/dsl-array-map-indexing/0011/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -16,3 +17,4 @@
   },
   "z": [1, 2, 3]
 }
+]
diff --git a/test/cases/dsl-array-map-indexing/0012/expout b/test/cases/dsl-array-map-indexing/0012/expout
index 85883cf32..168ad925d 100644
--- a/test/cases/dsl-array-map-indexing/0012/expout
+++ b/test/cases/dsl-array-map-indexing/0012/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -16,3 +17,4 @@
   },
   "z": "x"
 }
+]
diff --git a/test/cases/dsl-array-map-indexing/0013/expout b/test/cases/dsl-array-map-indexing/0013/expout
index 4f60fada6..cae49c68f 100644
--- a/test/cases/dsl-array-map-indexing/0013/expout
+++ b/test/cases/dsl-array-map-indexing/0013/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -16,3 +17,4 @@
   },
   "z": [1, 2, 3]
 }
+]
diff --git a/test/cases/dsl-arrayify/0001/expout b/test/cases/dsl-arrayify/0001/expout
index c6e55f3e3..d8eb9ea39 100644
--- a/test/cases/dsl-arrayify/0001/expout
+++ b/test/cases/dsl-arrayify/0001/expout
@@ -1,4 +1,6 @@
+[
 {
   "i": 1,
   "x": ["a", "b", "c"]
 }
+]
diff --git a/test/cases/dsl-arrayify/0002/expout b/test/cases/dsl-arrayify/0002/expout
index d55b0b5c5..4e9246c0a 100644
--- a/test/cases/dsl-arrayify/0002/expout
+++ b/test/cases/dsl-arrayify/0002/expout
@@ -1,3 +1,4 @@
+[
 {
   "i": 1,
   "x": {
@@ -6,3 +7,4 @@
     "2": "c"
   }
 }
+]
diff --git a/test/cases/dsl-arrayify/0003/expout b/test/cases/dsl-arrayify/0003/expout
index fe5c51a9d..983b7ee3f 100644
--- a/test/cases/dsl-arrayify/0003/expout
+++ b/test/cases/dsl-arrayify/0003/expout
@@ -1,3 +1,4 @@
+[
 {
   "i": 1,
   "x": {
@@ -6,3 +7,4 @@
     "5": "c"
   }
 }
+]
diff --git a/test/cases/dsl-arrayify/0004/expout b/test/cases/dsl-arrayify/0004/expout
index ef2957e0b..e1f061515 100644
--- a/test/cases/dsl-arrayify/0004/expout
+++ b/test/cases/dsl-arrayify/0004/expout
@@ -1,6 +1,8 @@
+[
 {
   "i": 1,
   "x": {
     "s": ["a", "b", "c"]
   }
 }
+]
diff --git a/test/cases/dsl-arrayify/0005/expout b/test/cases/dsl-arrayify/0005/expout
index 7f2fa918d..a2e17a75d 100644
--- a/test/cases/dsl-arrayify/0005/expout
+++ b/test/cases/dsl-arrayify/0005/expout
@@ -1,3 +1,4 @@
+[
 {
   "i": 1,
   "x": [
@@ -5,3 +6,4 @@
     ["d", "e", "f"]
   ]
 }
+]
diff --git a/test/cases/dsl-clean-whitespace/0001/expout b/test/cases/dsl-clean-whitespace/0001/expout
index 3d39772ba..0d62bc370 100644
--- a/test/cases/dsl-clean-whitespace/0001/expout
+++ b/test/cases/dsl-clean-whitespace/0001/expout
@@ -1,96 +1,98 @@
+[
 {
   "n": 1,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 2,
   "a": "xy ",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 3,
   "a": "xy  ",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 4,
   "a": "xy   ",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 5,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 6,
   "a": " xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 7,
   "a": "  xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 8,
   "a": "   xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 9,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 10,
   "a": " xy ",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 11,
   "a": "  xy  ",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 12,
   "a": "   xy   ",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 13,
   "a": "",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 14,
   "a": "  ",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 15,
   "a": "    ",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 16,
   "a": "      ",
   "b  ": 2,
   "  c": 3
 }
+]
diff --git a/test/cases/dsl-clean-whitespace/0002/expout b/test/cases/dsl-clean-whitespace/0002/expout
index 8d69e7f8d..982d3a26a 100644
--- a/test/cases/dsl-clean-whitespace/0002/expout
+++ b/test/cases/dsl-clean-whitespace/0002/expout
@@ -1,96 +1,98 @@
+[
 {
   "n": 1,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 2,
   "a": "xy ",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 3,
   "a": "xy  ",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 4,
   "a": "xy   ",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 5,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 6,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 7,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 8,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 9,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 10,
   "a": "xy ",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 11,
   "a": "xy  ",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 12,
   "a": "xy   ",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 13,
   "a": "",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 14,
   "a": "",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 15,
   "a": "",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 16,
   "a": "",
   "b  ": 2,
   "  c": 3
 }
+]
diff --git a/test/cases/dsl-clean-whitespace/0003/expout b/test/cases/dsl-clean-whitespace/0003/expout
index c460d8d45..3afdeed27 100644
--- a/test/cases/dsl-clean-whitespace/0003/expout
+++ b/test/cases/dsl-clean-whitespace/0003/expout
@@ -1,96 +1,98 @@
+[
 {
   "n": 1,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 2,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 3,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 4,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 5,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 6,
   "a": " xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 7,
   "a": "  xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 8,
   "a": "   xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 9,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 10,
   "a": " xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 11,
   "a": "  xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 12,
   "a": "   xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 13,
   "a": "",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 14,
   "a": "",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 15,
   "a": "",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 16,
   "a": "",
   "b  ": 2,
   "  c": 3
 }
+]
diff --git a/test/cases/dsl-clean-whitespace/0004/expout b/test/cases/dsl-clean-whitespace/0004/expout
index 51890d9df..fb608f2c0 100644
--- a/test/cases/dsl-clean-whitespace/0004/expout
+++ b/test/cases/dsl-clean-whitespace/0004/expout
@@ -1,96 +1,98 @@
+[
 {
   "n": 1,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 2,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 3,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 4,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 5,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 6,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 7,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 8,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 9,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 10,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 11,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 12,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 13,
   "a": "",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 14,
   "a": "",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 15,
   "a": "",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 16,
   "a": "",
   "b  ": 2,
   "  c": 3
 }
+]
diff --git a/test/cases/dsl-clean-whitespace/0005/expout b/test/cases/dsl-clean-whitespace/0005/expout
index 9ee8580e4..088d28a4e 100644
--- a/test/cases/dsl-clean-whitespace/0005/expout
+++ b/test/cases/dsl-clean-whitespace/0005/expout
@@ -1,96 +1,98 @@
+[
 {
   "n": 1,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 2,
   "a": "xy ",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 3,
   "a": "xy ",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 4,
   "a": "xy ",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 5,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 6,
   "a": " xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 7,
   "a": " xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 8,
   "a": " xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 9,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 10,
   "a": " xy ",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 11,
   "a": " xy ",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 12,
   "a": " xy ",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 13,
   "a": "",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 14,
   "a": " ",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 15,
   "a": " ",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 16,
   "a": " ",
   "b  ": 2,
   "  c": 3
 }
+]
diff --git a/test/cases/dsl-clean-whitespace/0006/expout b/test/cases/dsl-clean-whitespace/0006/expout
index 51890d9df..fb608f2c0 100644
--- a/test/cases/dsl-clean-whitespace/0006/expout
+++ b/test/cases/dsl-clean-whitespace/0006/expout
@@ -1,96 +1,98 @@
+[
 {
   "n": 1,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 2,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 3,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 4,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 5,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 6,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 7,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 8,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 9,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 10,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 11,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 12,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 13,
   "a": "",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 14,
   "a": "",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 15,
   "a": "",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 16,
   "a": "",
   "b  ": 2,
   "  c": 3
 }
+]
diff --git a/test/cases/dsl-clean-whitespace/0007/expout b/test/cases/dsl-clean-whitespace/0007/expout
index 0c45e243c..d67ce62c9 100644
--- a/test/cases/dsl-clean-whitespace/0007/expout
+++ b/test/cases/dsl-clean-whitespace/0007/expout
@@ -1,96 +1,98 @@
+[
 {
   "n": 1,
   "a": "xy",
   "b": 2,
   "c": 3
-}
+},
 {
   "n": 2,
   "a": "xy ",
   "b": 2,
   "c": 3
-}
+},
 {
   "n": 3,
   "a": "xy  ",
   "b": 2,
   "c": 3
-}
+},
 {
   "n": 4,
   "a": "xy   ",
   "b": 2,
   "c": 3
-}
+},
 {
   "n": 5,
   "a": "xy",
   "b": 2,
   "c": 3
-}
+},
 {
   "n": 6,
   "a": " xy",
   "b": 2,
   "c": 3
-}
+},
 {
   "n": 7,
   "a": "  xy",
   "b": 2,
   "c": 3
-}
+},
 {
   "n": 8,
   "a": "   xy",
   "b": 2,
   "c": 3
-}
+},
 {
   "n": 9,
   "a": "xy",
   "b": 2,
   "c": 3
-}
+},
 {
   "n": 10,
   "a": " xy ",
   "b": 2,
   "c": 3
-}
+},
 {
   "n": 11,
   "a": "  xy  ",
   "b": 2,
   "c": 3
-}
+},
 {
   "n": 12,
   "a": "   xy   ",
   "b": 2,
   "c": 3
-}
+},
 {
   "n": 13,
   "a": "",
   "b": 2,
   "c": 3
-}
+},
 {
   "n": 14,
   "a": "  ",
   "b": 2,
   "c": 3
-}
+},
 {
   "n": 15,
   "a": "    ",
   "b": 2,
   "c": 3
-}
+},
 {
   "n": 16,
   "a": "      ",
   "b": 2,
   "c": 3
 }
+]
diff --git a/test/cases/dsl-clean-whitespace/0008/expout b/test/cases/dsl-clean-whitespace/0008/expout
index 51890d9df..fb608f2c0 100644
--- a/test/cases/dsl-clean-whitespace/0008/expout
+++ b/test/cases/dsl-clean-whitespace/0008/expout
@@ -1,96 +1,98 @@
+[
 {
   "n": 1,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 2,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 3,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 4,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 5,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 6,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 7,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 8,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 9,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 10,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 11,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 12,
   "a": "xy",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 13,
   "a": "",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 14,
   "a": "",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 15,
   "a": "",
   "b  ": 2,
   "  c": 3
-}
+},
 {
   "n": 16,
   "a": "",
   "b  ": 2,
   "  c": 3
 }
+]
diff --git a/test/cases/dsl-clean-whitespace/0009/expout b/test/cases/dsl-clean-whitespace/0009/expout
index 5886f2b3b..651ee27b1 100644
--- a/test/cases/dsl-clean-whitespace/0009/expout
+++ b/test/cases/dsl-clean-whitespace/0009/expout
@@ -1,96 +1,98 @@
+[
 {
   "n": 1,
   "a": "xy",
   "b": 2,
   "c": 3
-}
+},
 {
   "n": 2,
   "a": "xy",
   "b": 2,
   "c": 3
-}
+},
 {
   "n": 3,
   "a": "xy",
   "b": 2,
   "c": 3
-}
+},
 {
   "n": 4,
   "a": "xy",
   "b": 2,
   "c": 3
-}
+},
 {
   "n": 5,
   "a": "xy",
   "b": 2,
   "c": 3
-}
+},
 {
   "n": 6,
   "a": "xy",
   "b": 2,
   "c": 3
-}
+},
 {
   "n": 7,
   "a": "xy",
   "b": 2,
   "c": 3
-}
+},
 {
   "n": 8,
   "a": "xy",
   "b": 2,
   "c": 3
-}
+},
 {
   "n": 9,
   "a": "xy",
   "b": 2,
   "c": 3
-}
+},
 {
   "n": 10,
   "a": "xy",
   "b": 2,
   "c": 3
-}
+},
 {
   "n": 11,
   "a": "xy",
   "b": 2,
   "c": 3
-}
+},
 {
   "n": 12,
   "a": "xy",
   "b": 2,
   "c": 3
-}
+},
 {
   "n": 13,
   "a": "",
   "b": 2,
   "c": 3
-}
+},
 {
   "n": 14,
   "a": "",
   "b": 2,
   "c": 3
-}
+},
 {
   "n": 15,
   "a": "",
   "b": 2,
   "c": 3
-}
+},
 {
   "n": 16,
   "a": "",
   "b": 2,
   "c": 3
 }
+]
diff --git a/test/cases/dsl-emit-basic-indexing/0012-no-indexed-nonlashed-emit-map-all/expout b/test/cases/dsl-emit-basic-indexing/0012-no-indexed-nonlashed-emit-map-all/expout
index 4e1d80fdf..49189271e 100644
--- a/test/cases/dsl-emit-basic-indexing/0012-no-indexed-nonlashed-emit-map-all/expout
+++ b/test/cases/dsl-emit-basic-indexing/0012-no-indexed-nonlashed-emit-map-all/expout
@@ -20,19 +20,21 @@
     }
   }
 }
+[
 {
   "wye": 1,
   "zee": 1
-}
+},
 {
   "wye": 1,
   "zee": 1
-}
+},
 {
   "wye": 2,
   "zee": 4
-}
+},
 {
   "wye": 6,
   "zee": 8
 }
+]
diff --git a/test/cases/dsl-emit-basic-indexing/0013-no-indexed-nonlashed-emit-map-single/expout b/test/cases/dsl-emit-basic-indexing/0013-no-indexed-nonlashed-emit-map-single/expout
index 10911769b..a093cc914 100644
--- a/test/cases/dsl-emit-basic-indexing/0013-no-indexed-nonlashed-emit-map-single/expout
+++ b/test/cases/dsl-emit-basic-indexing/0013-no-indexed-nonlashed-emit-map-single/expout
@@ -20,11 +20,13 @@
     }
   }
 }
+[
 {
   "wye": 2,
   "zee": 4
-}
+},
 {
   "wye": 6,
   "zee": 8
 }
+]
diff --git a/test/cases/dsl-emit-basic-indexing/0022-no-indexed-nonlashed-emitp-map-all/expout b/test/cases/dsl-emit-basic-indexing/0022-no-indexed-nonlashed-emitp-map-all/expout
index d0d1b5174..cdbcedf10 100644
--- a/test/cases/dsl-emit-basic-indexing/0022-no-indexed-nonlashed-emitp-map-all/expout
+++ b/test/cases/dsl-emit-basic-indexing/0022-no-indexed-nonlashed-emitp-map-all/expout
@@ -20,6 +20,7 @@
     }
   }
 }
+[
 {
   "count": {
     "vee": {
@@ -31,7 +32,7 @@
       "zee": 1
     }
   }
-}
+},
 {
   "sum": {
     "vee": {
@@ -44,3 +45,4 @@
     }
   }
 }
+]
diff --git a/test/cases/dsl-emit-basic-indexing/0023-no-indexed-nonlashed-emitp-map-single/expout b/test/cases/dsl-emit-basic-indexing/0023-no-indexed-nonlashed-emitp-map-single/expout
index 1ab178ed0..bb44d3cca 100644
--- a/test/cases/dsl-emit-basic-indexing/0023-no-indexed-nonlashed-emitp-map-single/expout
+++ b/test/cases/dsl-emit-basic-indexing/0023-no-indexed-nonlashed-emitp-map-single/expout
@@ -20,6 +20,7 @@
     }
   }
 }
+[
 {
   "sum": {
     "vee": {
@@ -32,3 +33,4 @@
     }
   }
 }
+]
diff --git a/test/cases/dsl-emit-basic-indexing/0031-no-indexed-lashed-emit-maps/expout b/test/cases/dsl-emit-basic-indexing/0031-no-indexed-lashed-emit-maps/expout
index 4e1d80fdf..49189271e 100644
--- a/test/cases/dsl-emit-basic-indexing/0031-no-indexed-lashed-emit-maps/expout
+++ b/test/cases/dsl-emit-basic-indexing/0031-no-indexed-lashed-emit-maps/expout
@@ -20,19 +20,21 @@
     }
   }
 }
+[
 {
   "wye": 1,
   "zee": 1
-}
+},
 {
   "wye": 1,
   "zee": 1
-}
+},
 {
   "wye": 2,
   "zee": 4
-}
+},
 {
   "wye": 6,
   "zee": 8
 }
+]
diff --git a/test/cases/dsl-emit-basic-indexing/0041-no-indexed-lashed-emitp-maps/expout b/test/cases/dsl-emit-basic-indexing/0041-no-indexed-lashed-emitp-maps/expout
index fc337a6d3..79a13ad44 100644
--- a/test/cases/dsl-emit-basic-indexing/0041-no-indexed-lashed-emitp-maps/expout
+++ b/test/cases/dsl-emit-basic-indexing/0041-no-indexed-lashed-emitp-maps/expout
@@ -20,6 +20,7 @@
     }
   }
 }
+[
 {
   "count": {
     "vee": {
@@ -42,3 +43,4 @@
     }
   }
 }
+]
diff --git a/test/cases/dsl-emit-basic-indexing/0050-under-indexed-nonlashed-emit-single-map/expout b/test/cases/dsl-emit-basic-indexing/0050-under-indexed-nonlashed-emit-single-map/expout
index 375cc670f..c3fab29db 100644
--- a/test/cases/dsl-emit-basic-indexing/0050-under-indexed-nonlashed-emit-single-map/expout
+++ b/test/cases/dsl-emit-basic-indexing/0050-under-indexed-nonlashed-emit-single-map/expout
@@ -20,13 +20,15 @@
     }
   }
 }
+[
 {
   "a": "vee",
   "wye": 2,
   "zee": 4
-}
+},
 {
   "a": "eks",
   "wye": 6,
   "zee": 8
 }
+]
diff --git a/test/cases/dsl-emit-basic-indexing/0051-at-indexed-nonlashed-emit-single-map/expout b/test/cases/dsl-emit-basic-indexing/0051-at-indexed-nonlashed-emit-single-map/expout
index f83b855a5..2a9b7e83b 100644
--- a/test/cases/dsl-emit-basic-indexing/0051-at-indexed-nonlashed-emit-single-map/expout
+++ b/test/cases/dsl-emit-basic-indexing/0051-at-indexed-nonlashed-emit-single-map/expout
@@ -20,23 +20,25 @@
     }
   }
 }
+[
 {
   "a": "vee",
   "b": "wye",
   "sum": 2
-}
+},
 {
   "a": "vee",
   "b": "zee",
   "sum": 4
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "sum": 6
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "sum": 8
 }
+]
diff --git a/test/cases/dsl-emit-basic-indexing/0052-over-indexed-nonlashed-emit-single-map/expout b/test/cases/dsl-emit-basic-indexing/0052-over-indexed-nonlashed-emit-single-map/expout
index f83b855a5..2a9b7e83b 100644
--- a/test/cases/dsl-emit-basic-indexing/0052-over-indexed-nonlashed-emit-single-map/expout
+++ b/test/cases/dsl-emit-basic-indexing/0052-over-indexed-nonlashed-emit-single-map/expout
@@ -20,23 +20,25 @@
     }
   }
 }
+[
 {
   "a": "vee",
   "b": "wye",
   "sum": 2
-}
+},
 {
   "a": "vee",
   "b": "zee",
   "sum": 4
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "sum": 6
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "sum": 8
 }
+]
diff --git a/test/cases/dsl-emit-basic-indexing/0053-under-indexed-nonlashed-emit-all-maps/expout b/test/cases/dsl-emit-basic-indexing/0053-under-indexed-nonlashed-emit-all-maps/expout
index 6ad2a61f3..2ab30c566 100644
--- a/test/cases/dsl-emit-basic-indexing/0053-under-indexed-nonlashed-emit-all-maps/expout
+++ b/test/cases/dsl-emit-basic-indexing/0053-under-indexed-nonlashed-emit-all-maps/expout
@@ -20,23 +20,25 @@
     }
   }
 }
+[
 {
   "a": "vee",
   "wye": 1,
   "zee": 1
-}
+},
 {
   "a": "eks",
   "wye": 1,
   "zee": 1
-}
+},
 {
   "a": "vee",
   "wye": 2,
   "zee": 4
-}
+},
 {
   "a": "eks",
   "wye": 6,
   "zee": 8
 }
+]
diff --git a/test/cases/dsl-emit-basic-indexing/0054-at-indexed-nonlashed-emit-all-maps/expout b/test/cases/dsl-emit-basic-indexing/0054-at-indexed-nonlashed-emit-all-maps/expout
index acea4495a..90e46e6e3 100644
--- a/test/cases/dsl-emit-basic-indexing/0054-at-indexed-nonlashed-emit-all-maps/expout
+++ b/test/cases/dsl-emit-basic-indexing/0054-at-indexed-nonlashed-emit-all-maps/expout
@@ -20,43 +20,45 @@
     }
   }
 }
+[
 {
   "a": "vee",
   "b": "wye",
   "count": 1
-}
+},
 {
   "a": "vee",
   "b": "zee",
   "count": 1
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "count": 1
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "count": 1
-}
+},
 {
   "a": "vee",
   "b": "wye",
   "sum": 2
-}
+},
 {
   "a": "vee",
   "b": "zee",
   "sum": 4
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "sum": 6
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "sum": 8
 }
+]
diff --git a/test/cases/dsl-emit-basic-indexing/0055-over-indexed-nonlashed-emit-all-maps/expout b/test/cases/dsl-emit-basic-indexing/0055-over-indexed-nonlashed-emit-all-maps/expout
index acea4495a..90e46e6e3 100644
--- a/test/cases/dsl-emit-basic-indexing/0055-over-indexed-nonlashed-emit-all-maps/expout
+++ b/test/cases/dsl-emit-basic-indexing/0055-over-indexed-nonlashed-emit-all-maps/expout
@@ -20,43 +20,45 @@
     }
   }
 }
+[
 {
   "a": "vee",
   "b": "wye",
   "count": 1
-}
+},
 {
   "a": "vee",
   "b": "zee",
   "count": 1
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "count": 1
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "count": 1
-}
+},
 {
   "a": "vee",
   "b": "wye",
   "sum": 2
-}
+},
 {
   "a": "vee",
   "b": "zee",
   "sum": 4
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "sum": 6
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "sum": 8
 }
+]
diff --git a/test/cases/dsl-emit-basic-indexing/0060-under-indexed-lashed-emit-maps/expout b/test/cases/dsl-emit-basic-indexing/0060-under-indexed-lashed-emit-maps/expout
index 375cc670f..c3fab29db 100644
--- a/test/cases/dsl-emit-basic-indexing/0060-under-indexed-lashed-emit-maps/expout
+++ b/test/cases/dsl-emit-basic-indexing/0060-under-indexed-lashed-emit-maps/expout
@@ -20,13 +20,15 @@
     }
   }
 }
+[
 {
   "a": "vee",
   "wye": 2,
   "zee": 4
-}
+},
 {
   "a": "eks",
   "wye": 6,
   "zee": 8
 }
+]
diff --git a/test/cases/dsl-emit-basic-indexing/0061-at-indexed-lashed-emit-maps/expout b/test/cases/dsl-emit-basic-indexing/0061-at-indexed-lashed-emit-maps/expout
index 628a56226..393165edb 100644
--- a/test/cases/dsl-emit-basic-indexing/0061-at-indexed-lashed-emit-maps/expout
+++ b/test/cases/dsl-emit-basic-indexing/0061-at-indexed-lashed-emit-maps/expout
@@ -20,27 +20,29 @@
     }
   }
 }
+[
 {
   "a": "vee",
   "b": "wye",
   "count": 1,
   "sum": 2
-}
+},
 {
   "a": "vee",
   "b": "zee",
   "count": 1,
   "sum": 4
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "count": 1,
   "sum": 6
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "count": 1,
   "sum": 8
 }
+]
diff --git a/test/cases/dsl-emit-basic-indexing/0062-over-indexed-lashed-emit-maps/expout b/test/cases/dsl-emit-basic-indexing/0062-over-indexed-lashed-emit-maps/expout
index 628a56226..393165edb 100644
--- a/test/cases/dsl-emit-basic-indexing/0062-over-indexed-lashed-emit-maps/expout
+++ b/test/cases/dsl-emit-basic-indexing/0062-over-indexed-lashed-emit-maps/expout
@@ -20,27 +20,29 @@
     }
   }
 }
+[
 {
   "a": "vee",
   "b": "wye",
   "count": 1,
   "sum": 2
-}
+},
 {
   "a": "vee",
   "b": "zee",
   "count": 1,
   "sum": 4
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "count": 1,
   "sum": 6
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "count": 1,
   "sum": 8
 }
+]
diff --git a/test/cases/dsl-emit-basic-indexing/0070-under-indexed-nonlashed-emitp-single-map/expout b/test/cases/dsl-emit-basic-indexing/0070-under-indexed-nonlashed-emitp-single-map/expout
index fd0103706..63d689af4 100644
--- a/test/cases/dsl-emit-basic-indexing/0070-under-indexed-nonlashed-emitp-single-map/expout
+++ b/test/cases/dsl-emit-basic-indexing/0070-under-indexed-nonlashed-emitp-single-map/expout
@@ -20,13 +20,14 @@
     }
   }
 }
+[
 {
   "a": "vee",
   "sum": {
     "wye": 2,
     "zee": 4
   }
-}
+},
 {
   "a": "eks",
   "sum": {
@@ -34,3 +35,4 @@
     "zee": 8
   }
 }
+]
diff --git a/test/cases/dsl-emit-basic-indexing/0071-at-indexed-nonlashed-emitp-single-map/expout b/test/cases/dsl-emit-basic-indexing/0071-at-indexed-nonlashed-emitp-single-map/expout
index f83b855a5..2a9b7e83b 100644
--- a/test/cases/dsl-emit-basic-indexing/0071-at-indexed-nonlashed-emitp-single-map/expout
+++ b/test/cases/dsl-emit-basic-indexing/0071-at-indexed-nonlashed-emitp-single-map/expout
@@ -20,23 +20,25 @@
     }
   }
 }
+[
 {
   "a": "vee",
   "b": "wye",
   "sum": 2
-}
+},
 {
   "a": "vee",
   "b": "zee",
   "sum": 4
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "sum": 6
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "sum": 8
 }
+]
diff --git a/test/cases/dsl-emit-basic-indexing/0072-over-indexed-nonlashed-emitp-single-map/expout b/test/cases/dsl-emit-basic-indexing/0072-over-indexed-nonlashed-emitp-single-map/expout
index f83b855a5..2a9b7e83b 100644
--- a/test/cases/dsl-emit-basic-indexing/0072-over-indexed-nonlashed-emitp-single-map/expout
+++ b/test/cases/dsl-emit-basic-indexing/0072-over-indexed-nonlashed-emitp-single-map/expout
@@ -20,23 +20,25 @@
     }
   }
 }
+[
 {
   "a": "vee",
   "b": "wye",
   "sum": 2
-}
+},
 {
   "a": "vee",
   "b": "zee",
   "sum": 4
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "sum": 6
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "sum": 8
 }
+]
diff --git a/test/cases/dsl-emit-basic-indexing/0073-under-indexed-nonlashed-emitp-all-maps/expout b/test/cases/dsl-emit-basic-indexing/0073-under-indexed-nonlashed-emitp-all-maps/expout
index 93350f50b..435612fd0 100644
--- a/test/cases/dsl-emit-basic-indexing/0073-under-indexed-nonlashed-emitp-all-maps/expout
+++ b/test/cases/dsl-emit-basic-indexing/0073-under-indexed-nonlashed-emitp-all-maps/expout
@@ -20,27 +20,28 @@
     }
   }
 }
+[
 {
   "a": "vee",
   "count": {
     "wye": 1,
     "zee": 1
   }
-}
+},
 {
   "a": "eks",
   "count": {
     "wye": 1,
     "zee": 1
   }
-}
+},
 {
   "a": "vee",
   "sum": {
     "wye": 2,
     "zee": 4
   }
-}
+},
 {
   "a": "eks",
   "sum": {
@@ -48,3 +49,4 @@
     "zee": 8
   }
 }
+]
diff --git a/test/cases/dsl-emit-basic-indexing/0074-at-indexed-nonlashed-emitp-all-maps/expout b/test/cases/dsl-emit-basic-indexing/0074-at-indexed-nonlashed-emitp-all-maps/expout
index acea4495a..90e46e6e3 100644
--- a/test/cases/dsl-emit-basic-indexing/0074-at-indexed-nonlashed-emitp-all-maps/expout
+++ b/test/cases/dsl-emit-basic-indexing/0074-at-indexed-nonlashed-emitp-all-maps/expout
@@ -20,43 +20,45 @@
     }
   }
 }
+[
 {
   "a": "vee",
   "b": "wye",
   "count": 1
-}
+},
 {
   "a": "vee",
   "b": "zee",
   "count": 1
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "count": 1
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "count": 1
-}
+},
 {
   "a": "vee",
   "b": "wye",
   "sum": 2
-}
+},
 {
   "a": "vee",
   "b": "zee",
   "sum": 4
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "sum": 6
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "sum": 8
 }
+]
diff --git a/test/cases/dsl-emit-basic-indexing/0075-over-indexed-nonlashed-emitp-all-maps/expout b/test/cases/dsl-emit-basic-indexing/0075-over-indexed-nonlashed-emitp-all-maps/expout
index acea4495a..90e46e6e3 100644
--- a/test/cases/dsl-emit-basic-indexing/0075-over-indexed-nonlashed-emitp-all-maps/expout
+++ b/test/cases/dsl-emit-basic-indexing/0075-over-indexed-nonlashed-emitp-all-maps/expout
@@ -20,43 +20,45 @@
     }
   }
 }
+[
 {
   "a": "vee",
   "b": "wye",
   "count": 1
-}
+},
 {
   "a": "vee",
   "b": "zee",
   "count": 1
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "count": 1
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "count": 1
-}
+},
 {
   "a": "vee",
   "b": "wye",
   "sum": 2
-}
+},
 {
   "a": "vee",
   "b": "zee",
   "sum": 4
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "sum": 6
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "sum": 8
 }
+]
diff --git a/test/cases/dsl-emit-basic-indexing/0080-under-indexed-lashed-emitp-maps/expout b/test/cases/dsl-emit-basic-indexing/0080-under-indexed-lashed-emitp-maps/expout
index fdf915a4e..0284c0f4b 100644
--- a/test/cases/dsl-emit-basic-indexing/0080-under-indexed-lashed-emitp-maps/expout
+++ b/test/cases/dsl-emit-basic-indexing/0080-under-indexed-lashed-emitp-maps/expout
@@ -20,6 +20,7 @@
     }
   }
 }
+[
 {
   "a": "vee",
   "count": {
@@ -30,7 +31,7 @@
     "wye": 2,
     "zee": 4
   }
-}
+},
 {
   "a": "eks",
   "count": {
@@ -42,3 +43,4 @@
     "zee": 8
   }
 }
+]
diff --git a/test/cases/dsl-emit-basic-indexing/0081-at-indexed-lashed-emitp-maps/expout b/test/cases/dsl-emit-basic-indexing/0081-at-indexed-lashed-emitp-maps/expout
index 628a56226..393165edb 100644
--- a/test/cases/dsl-emit-basic-indexing/0081-at-indexed-lashed-emitp-maps/expout
+++ b/test/cases/dsl-emit-basic-indexing/0081-at-indexed-lashed-emitp-maps/expout
@@ -20,27 +20,29 @@
     }
   }
 }
+[
 {
   "a": "vee",
   "b": "wye",
   "count": 1,
   "sum": 2
-}
+},
 {
   "a": "vee",
   "b": "zee",
   "count": 1,
   "sum": 4
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "count": 1,
   "sum": 6
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "count": 1,
   "sum": 8
 }
+]
diff --git a/test/cases/dsl-emit-basic-indexing/0082-over-indexed-lashed-emitp-maps/expout b/test/cases/dsl-emit-basic-indexing/0082-over-indexed-lashed-emitp-maps/expout
index 628a56226..393165edb 100644
--- a/test/cases/dsl-emit-basic-indexing/0082-over-indexed-lashed-emitp-maps/expout
+++ b/test/cases/dsl-emit-basic-indexing/0082-over-indexed-lashed-emitp-maps/expout
@@ -20,27 +20,29 @@
     }
   }
 }
+[
 {
   "a": "vee",
   "b": "wye",
   "count": 1,
   "sum": 2
-}
+},
 {
   "a": "vee",
   "b": "zee",
   "count": 1,
   "sum": 4
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "count": 1,
   "sum": 6
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "count": 1,
   "sum": 8
 }
+]
diff --git a/test/cases/dsl-flatten-unflatten/0004/expout b/test/cases/dsl-flatten-unflatten/0004/expout
index daa09fd8c..c7e5ffff0 100644
--- a/test/cases/dsl-flatten-unflatten/0004/expout
+++ b/test/cases/dsl-flatten-unflatten/0004/expout
@@ -1,10 +1,11 @@
+[
 {
   "a": 1,
   "b": {
     "c": 2,
     "d": 3
   }
-}
+},
 {
   "a": 1,
   "b": {
@@ -17,13 +18,13 @@
       "y": 5
     }
   }
-}
+},
 {
   "a": 1,
   "b": {
     "c": [2, 3]
   }
-}
+},
 {
   "a": 1,
   "b": [
@@ -37,3 +38,4 @@
     }
   ]
 }
+]
diff --git a/test/cases/dsl-flatten-unflatten/0005/expout b/test/cases/dsl-flatten-unflatten/0005/expout
index e74084a89..fce374bde 100644
--- a/test/cases/dsl-flatten-unflatten/0005/expout
+++ b/test/cases/dsl-flatten-unflatten/0005/expout
@@ -1,10 +1,11 @@
+[
 {
   "a": 1,
   "b": {
     "b.c": 2,
     "b.d": 3
   }
-}
+},
 {
   "a": 1,
   "b": {
@@ -13,14 +14,14 @@
     "b.d.x": 4,
     "b.d.y": 5
   }
-}
+},
 {
   "a": 1,
   "b": {
     "b.c.1": 2,
     "b.c.2": 3
   }
-}
+},
 {
   "a": 1,
   "b": {
@@ -30,3 +31,4 @@
     "b.2.y": 5
   }
 }
+]
diff --git a/test/cases/dsl-flatten-unflatten/0007/expout b/test/cases/dsl-flatten-unflatten/0007/expout
index 0a3d2cfeb..9a45bc186 100644
--- a/test/cases/dsl-flatten-unflatten/0007/expout
+++ b/test/cases/dsl-flatten-unflatten/0007/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -25,3 +26,4 @@
     "emtpy4": []
   }
 }
+]
diff --git a/test/cases/dsl-flatten-unflatten/0008/expout b/test/cases/dsl-flatten-unflatten/0008/expout
index 5da45409d..0a5168c01 100644
--- a/test/cases/dsl-flatten-unflatten/0008/expout
+++ b/test/cases/dsl-flatten-unflatten/0008/expout
@@ -1,5 +1,7 @@
+[
 {
   "a": 5,
   "b": [6, 7, 8],
   "c": 9
 }
+]
diff --git a/test/cases/dsl-flatten-unflatten/0009/expout b/test/cases/dsl-flatten-unflatten/0009/expout
index 1539e9e12..8cc30fa4b 100644
--- a/test/cases/dsl-flatten-unflatten/0009/expout
+++ b/test/cases/dsl-flatten-unflatten/0009/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": 5,
   "b": {
@@ -6,3 +7,4 @@
   },
   "c": 9
 }
+]
diff --git a/test/cases/dsl-functional-tests/0051/expout b/test/cases/dsl-functional-tests/0051/expout
index 97353ee3a..d14a2c4d2 100644
--- a/test/cases/dsl-functional-tests/0051/expout
+++ b/test/cases/dsl-functional-tests/0051/expout
@@ -60,3 +60,5 @@
     "zsgnt": "int"
   }
 ]
+[
+]
diff --git a/test/cases/dsl-indexing/0002/expout b/test/cases/dsl-indexing/0002/expout
index 5838ffc53..9f036ff60 100644
--- a/test/cases/dsl-indexing/0002/expout
+++ b/test/cases/dsl-indexing/0002/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -13,7 +14,7 @@
       0.2520480696761337
     ]
   ]
-}
+},
 {
   "a": "eks",
   "b": "pan",
@@ -29,7 +30,7 @@
       0.3961455844854848
     ]
   ]
-}
+},
 {
   "a": "wye",
   "b": "wye",
@@ -45,7 +46,7 @@
       0.06922108872268748
     ]
   ]
-}
+},
 {
   "a": "eks",
   "b": "wye",
@@ -61,7 +62,7 @@
       0.05117950535296393
     ]
   ]
-}
+},
 {
   "a": "wye",
   "b": "pan",
@@ -77,7 +78,7 @@
       0.4951063394654227
     ]
   ]
-}
+},
 {
   "a": "zee",
   "b": "pan",
@@ -93,7 +94,7 @@
       0.259989842959225
     ]
   ]
-}
+},
 {
   "a": "eks",
   "b": "zee",
@@ -110,3 +111,4 @@
     ]
   ]
 }
+]
diff --git a/test/cases/dsl-indexing/0003/expout b/test/cases/dsl-indexing/0003/expout
index 23cf85e48..b3257ec92 100644
--- a/test/cases/dsl-indexing/0003/expout
+++ b/test/cases/dsl-indexing/0003/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -5,7 +6,7 @@
   "x": 0.3467901443380824,
   "y": 0.7268028627434533,
   "z": "pan"
-}
+},
 {
   "a": "eks",
   "b": "pan",
@@ -13,7 +14,7 @@
   "x": 0.7586799647899636,
   "y": 0.5221511083334797,
   "z": "eks"
-}
+},
 {
   "a": "wye",
   "b": "wye",
@@ -21,7 +22,7 @@
   "x": 0.20460330576630303,
   "y": 0.33831852551664776,
   "z": "wye"
-}
+},
 {
   "a": "eks",
   "b": "wye",
@@ -30,3 +31,4 @@
   "y": 0.13418874328430463,
   "z": "eks"
 }
+]
diff --git a/test/cases/dsl-indexing/0004/expout b/test/cases/dsl-indexing/0004/expout
index 423d6ae07..c2635b841 100644
--- a/test/cases/dsl-indexing/0004/expout
+++ b/test/cases/dsl-indexing/0004/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -11,7 +12,7 @@
     "x": 0.3467901443380824,
     "y": 0.7268028627434533
   }
-}
+},
 {
   "a": "eks",
   "b": "pan",
@@ -25,7 +26,7 @@
     "x": 0.7586799647899636,
     "y": 0.5221511083334797
   }
-}
+},
 {
   "a": "wye",
   "b": "wye",
@@ -39,7 +40,7 @@
     "x": 0.20460330576630303,
     "y": 0.33831852551664776
   }
-}
+},
 {
   "a": "eks",
   "b": "wye",
@@ -54,3 +55,4 @@
     "y": 0.13418874328430463
   }
 }
+]
diff --git a/test/cases/dsl-indexing/0005/expout b/test/cases/dsl-indexing/0005/expout
index 300efc36b..f6744911b 100644
--- a/test/cases/dsl-indexing/0005/expout
+++ b/test/cases/dsl-indexing/0005/expout
@@ -1,16 +1,18 @@
+[
+{
+  "s": 7,
+  "t": 8
+},
+{
+  "s": 7,
+  "t": 8
+},
+{
+  "s": 7,
+  "t": 8
+},
 {
   "s": 7,
   "t": 8
 }
-{
-  "s": 7,
-  "t": 8
-}
-{
-  "s": 7,
-  "t": 8
-}
-{
-  "s": 7,
-  "t": 8
-}
+]
diff --git a/test/cases/dsl-indexing/0006/expout b/test/cases/dsl-indexing/0006/expout
index 5f1395998..7f49db3e1 100644
--- a/test/cases/dsl-indexing/0006/expout
+++ b/test/cases/dsl-indexing/0006/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -5,7 +6,7 @@
   "x": 0.3467901443380824,
   "y": 0.7268028627434533,
   "st": 78
-}
+},
 {
   "a": "eks",
   "b": "pan",
@@ -13,7 +14,7 @@
   "x": 0.7586799647899636,
   "y": 0.5221511083334797,
   "st": 78
-}
+},
 {
   "a": "wye",
   "b": "wye",
@@ -21,7 +22,7 @@
   "x": 0.20460330576630303,
   "y": 0.33831852551664776,
   "st": 78
-}
+},
 {
   "a": "eks",
   "b": "wye",
@@ -30,3 +31,4 @@
   "y": 0.13418874328430463,
   "st": 78
 }
+]
diff --git a/test/cases/dsl-indexing/0007/expout b/test/cases/dsl-indexing/0007/expout
index 995eca459..474bd0b91 100644
--- a/test/cases/dsl-indexing/0007/expout
+++ b/test/cases/dsl-indexing/0007/expout
@@ -1,24 +1,25 @@
+[
 {
   "a": 78,
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": 78,
   "b": "pan",
   "i": 2,
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
-}
+},
 {
   "a": 78,
   "b": "wye",
   "i": 3,
   "x": 0.20460330576630303,
   "y": 0.33831852551664776
-}
+},
 {
   "a": 78,
   "b": "wye",
@@ -26,3 +27,4 @@
   "x": 0.38139939387114097,
   "y": 0.13418874328430463
 }
+]
diff --git a/test/cases/dsl-indexing/0008/expout b/test/cases/dsl-indexing/0008/expout
index 644d20140..3ce5a94d7 100644
--- a/test/cases/dsl-indexing/0008/expout
+++ b/test/cases/dsl-indexing/0008/expout
@@ -1,24 +1,25 @@
+[
 {
   "a": {},
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": {},
   "b": "pan",
   "i": 2,
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
-}
+},
 {
   "a": {},
   "b": "wye",
   "i": 3,
   "x": 0.20460330576630303,
   "y": 0.33831852551664776
-}
+},
 {
   "a": {},
   "b": "wye",
@@ -26,3 +27,4 @@
   "x": 0.38139939387114097,
   "y": 0.13418874328430463
 }
+]
diff --git a/test/cases/dsl-indexing/0014/expout b/test/cases/dsl-indexing/0014/expout
index c08512c86..a4865b5d6 100644
--- a/test/cases/dsl-indexing/0014/expout
+++ b/test/cases/dsl-indexing/0014/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -5,7 +6,7 @@
   "x": 0.3467901443380824,
   "y": 0.7268028627434533,
   "curi": 1
-}
+},
 {
   "a": "eks",
   "b": "pan",
@@ -14,7 +15,7 @@
   "y": 0.5221511083334797,
   "curi": 2,
   "lagi": 1
-}
+},
 {
   "a": "wye",
   "b": "wye",
@@ -23,7 +24,7 @@
   "y": 0.33831852551664776,
   "curi": 3,
   "lagi": 2
-}
+},
 {
   "a": "eks",
   "b": "wye",
@@ -33,3 +34,4 @@
   "curi": 4,
   "lagi": 3
 }
+]
diff --git a/test/cases/dsl-indexing/0015/expout b/test/cases/dsl-indexing/0015/expout
index 007940a91..6cb4639c0 100644
--- a/test/cases/dsl-indexing/0015/expout
+++ b/test/cases/dsl-indexing/0015/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -11,7 +12,7 @@
       }
     }
   }
-}
+},
 {
   "a": "eks",
   "b": "pan",
@@ -25,7 +26,7 @@
       }
     }
   }
-}
+},
 {
   "a": "wye",
   "b": "wye",
@@ -39,7 +40,7 @@
       }
     }
   }
-}
+},
 {
   "a": "eks",
   "b": "wye",
@@ -54,3 +55,4 @@
     }
   }
 }
+]
diff --git a/test/cases/dsl-indexing/0016/expout b/test/cases/dsl-indexing/0016/expout
index ad6ef37b6..374240c9c 100644
--- a/test/cases/dsl-indexing/0016/expout
+++ b/test/cases/dsl-indexing/0016/expout
@@ -1,4 +1,6 @@
+[
 {
   "a": (error),
   "b": "c"
 }
+]
diff --git a/test/cases/dsl-indexing/0017/expout b/test/cases/dsl-indexing/0017/expout
index efd683bfb..5eb60c4a8 100644
--- a/test/cases/dsl-indexing/0017/expout
+++ b/test/cases/dsl-indexing/0017/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -5,7 +6,7 @@
   "x": 0.3467901443380824,
   "y": 0.7268028627434533,
   "foo": 1
-}
+},
 {
   "a": "eks",
   "b": "pan",
@@ -13,7 +14,7 @@
   "x": 0.7586799647899636,
   "y": 0.5221511083334797,
   "foo": 2
-}
+},
 {
   "a": "wye",
   "b": "wye",
@@ -21,7 +22,7 @@
   "x": 0.20460330576630303,
   "y": 0.33831852551664776,
   "foo": 3
-}
+},
 {
   "a": "eks",
   "b": "wye",
@@ -30,3 +31,4 @@
   "y": 0.13418874328430463,
   "foo": 4
 }
+]
diff --git a/test/cases/dsl-indexing/0018/expout b/test/cases/dsl-indexing/0018/expout
index efd683bfb..5eb60c4a8 100644
--- a/test/cases/dsl-indexing/0018/expout
+++ b/test/cases/dsl-indexing/0018/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -5,7 +6,7 @@
   "x": 0.3467901443380824,
   "y": 0.7268028627434533,
   "foo": 1
-}
+},
 {
   "a": "eks",
   "b": "pan",
@@ -13,7 +14,7 @@
   "x": 0.7586799647899636,
   "y": 0.5221511083334797,
   "foo": 2
-}
+},
 {
   "a": "wye",
   "b": "wye",
@@ -21,7 +22,7 @@
   "x": 0.20460330576630303,
   "y": 0.33831852551664776,
   "foo": 3
-}
+},
 {
   "a": "eks",
   "b": "wye",
@@ -30,3 +31,4 @@
   "y": 0.13418874328430463,
   "foo": 4
 }
+]
diff --git a/test/cases/dsl-indexing/0019/expout b/test/cases/dsl-indexing/0019/expout
index 008558b4c..501819bc1 100644
--- a/test/cases/dsl-indexing/0019/expout
+++ b/test/cases/dsl-indexing/0019/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -7,7 +8,7 @@
   "foo": {
     "bar": 1
   }
-}
+},
 {
   "a": "eks",
   "b": "pan",
@@ -17,7 +18,7 @@
   "foo": {
     "bar": 2
   }
-}
+},
 {
   "a": "wye",
   "b": "wye",
@@ -27,7 +28,7 @@
   "foo": {
     "bar": 3
   }
-}
+},
 {
   "a": "eks",
   "b": "wye",
@@ -38,3 +39,4 @@
     "bar": 4
   }
 }
+]
diff --git a/test/cases/dsl-indexing/0020/expout b/test/cases/dsl-indexing/0020/expout
index 008558b4c..501819bc1 100644
--- a/test/cases/dsl-indexing/0020/expout
+++ b/test/cases/dsl-indexing/0020/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -7,7 +8,7 @@
   "foo": {
     "bar": 1
   }
-}
+},
 {
   "a": "eks",
   "b": "pan",
@@ -17,7 +18,7 @@
   "foo": {
     "bar": 2
   }
-}
+},
 {
   "a": "wye",
   "b": "wye",
@@ -27,7 +28,7 @@
   "foo": {
     "bar": 3
   }
-}
+},
 {
   "a": "eks",
   "b": "wye",
@@ -38,3 +39,4 @@
     "bar": 4
   }
 }
+]
diff --git a/test/cases/dsl-indexing/0021/expout b/test/cases/dsl-indexing/0021/expout
index 008558b4c..501819bc1 100644
--- a/test/cases/dsl-indexing/0021/expout
+++ b/test/cases/dsl-indexing/0021/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -7,7 +8,7 @@
   "foo": {
     "bar": 1
   }
-}
+},
 {
   "a": "eks",
   "b": "pan",
@@ -17,7 +18,7 @@
   "foo": {
     "bar": 2
   }
-}
+},
 {
   "a": "wye",
   "b": "wye",
@@ -27,7 +28,7 @@
   "foo": {
     "bar": 3
   }
-}
+},
 {
   "a": "eks",
   "b": "wye",
@@ -38,3 +39,4 @@
     "bar": 4
   }
 }
+]
diff --git a/test/cases/dsl-json-collection-output/0001/expout b/test/cases/dsl-json-collection-output/0001/expout
index b41480ad7..39aa76724 100644
--- a/test/cases/dsl-json-collection-output/0001/expout
+++ b/test/cases/dsl-json-collection-output/0001/expout
@@ -1,3 +1,5 @@
+[
 {
   "x": 1
 }
+]
diff --git a/test/cases/dsl-json-collection-output/0002/expout b/test/cases/dsl-json-collection-output/0002/expout
index 69633e2eb..ba334d00d 100644
--- a/test/cases/dsl-json-collection-output/0002/expout
+++ b/test/cases/dsl-json-collection-output/0002/expout
@@ -1,3 +1,5 @@
+[
 {
   "x": [1, 2, 3]
 }
+]
diff --git a/test/cases/dsl-json-collection-output/0003/expout b/test/cases/dsl-json-collection-output/0003/expout
index 4d06cde7a..d4950459f 100644
--- a/test/cases/dsl-json-collection-output/0003/expout
+++ b/test/cases/dsl-json-collection-output/0003/expout
@@ -1,3 +1,4 @@
+[
 {
   "x": [
     1,
@@ -5,3 +6,4 @@
     5
   ]
 }
+]
diff --git a/test/cases/dsl-json-collection-output/0004/expout b/test/cases/dsl-json-collection-output/0004/expout
index e374c3da0..f23fb0eb5 100644
--- a/test/cases/dsl-json-collection-output/0004/expout
+++ b/test/cases/dsl-json-collection-output/0004/expout
@@ -1,3 +1,4 @@
+[
 {
   "x": [
     1,
@@ -9,3 +10,4 @@
     7
   ]
 }
+]
diff --git a/test/cases/dsl-json-collection-output/0005/expout b/test/cases/dsl-json-collection-output/0005/expout
index 5a7a2b420..519630862 100644
--- a/test/cases/dsl-json-collection-output/0005/expout
+++ b/test/cases/dsl-json-collection-output/0005/expout
@@ -1,3 +1,5 @@
+[
 {
   "x": {}
 }
+]
diff --git a/test/cases/dsl-json-collection-output/0006/expout b/test/cases/dsl-json-collection-output/0006/expout
index 12911b7b1..1b579c09b 100644
--- a/test/cases/dsl-json-collection-output/0006/expout
+++ b/test/cases/dsl-json-collection-output/0006/expout
@@ -1,3 +1,4 @@
+[
 {
   "x": {
     "a": 1,
@@ -5,3 +6,4 @@
     "c": 3
   }
 }
+]
diff --git a/test/cases/dsl-json-collection-output/0007/expout b/test/cases/dsl-json-collection-output/0007/expout
index 2ba2ad7fd..c7fa7112d 100644
--- a/test/cases/dsl-json-collection-output/0007/expout
+++ b/test/cases/dsl-json-collection-output/0007/expout
@@ -1,3 +1,4 @@
+[
 {
   "x": {
     "a": 1,
@@ -9,3 +10,4 @@
     "f": 6
   }
 }
+]
diff --git a/test/cases/dsl-json-collection-output/0008/expout b/test/cases/dsl-json-collection-output/0008/expout
index fcd98884f..9402c9cf1 100644
--- a/test/cases/dsl-json-collection-output/0008/expout
+++ b/test/cases/dsl-json-collection-output/0008/expout
@@ -1,4 +1,6 @@
+[
 {
   "x": {},
   "y": 1
 }
+]
diff --git a/test/cases/dsl-json-collection-output/0009/expout b/test/cases/dsl-json-collection-output/0009/expout
index 1d8b00211..cb2e6811e 100644
--- a/test/cases/dsl-json-collection-output/0009/expout
+++ b/test/cases/dsl-json-collection-output/0009/expout
@@ -1,3 +1,4 @@
+[
 {
   "x": {
     "a": 1,
@@ -6,3 +7,4 @@
   },
   "y": 4
 }
+]
diff --git a/test/cases/dsl-json-collection-output/0010/expout b/test/cases/dsl-json-collection-output/0010/expout
index 588ff2490..2aa17f9b2 100644
--- a/test/cases/dsl-json-collection-output/0010/expout
+++ b/test/cases/dsl-json-collection-output/0010/expout
@@ -1,3 +1,4 @@
+[
 {
   "x": {
     "a": 1,
@@ -10,3 +11,4 @@
   },
   "y": 7
 }
+]
diff --git a/test/cases/dsl-json-collection-output/0011/expout b/test/cases/dsl-json-collection-output/0011/expout
index b41480ad7..39aa76724 100644
--- a/test/cases/dsl-json-collection-output/0011/expout
+++ b/test/cases/dsl-json-collection-output/0011/expout
@@ -1,3 +1,5 @@
+[
 {
   "x": 1
 }
+]
diff --git a/test/cases/dsl-json-collection-output/0012/expout b/test/cases/dsl-json-collection-output/0012/expout
index 69633e2eb..ba334d00d 100644
--- a/test/cases/dsl-json-collection-output/0012/expout
+++ b/test/cases/dsl-json-collection-output/0012/expout
@@ -1,3 +1,5 @@
+[
 {
   "x": [1, 2, 3]
 }
+]
diff --git a/test/cases/dsl-json-collection-output/0013/expout b/test/cases/dsl-json-collection-output/0013/expout
index 4d06cde7a..d4950459f 100644
--- a/test/cases/dsl-json-collection-output/0013/expout
+++ b/test/cases/dsl-json-collection-output/0013/expout
@@ -1,3 +1,4 @@
+[
 {
   "x": [
     1,
@@ -5,3 +6,4 @@
     5
   ]
 }
+]
diff --git a/test/cases/dsl-json-collection-output/0014/expout b/test/cases/dsl-json-collection-output/0014/expout
index e374c3da0..f23fb0eb5 100644
--- a/test/cases/dsl-json-collection-output/0014/expout
+++ b/test/cases/dsl-json-collection-output/0014/expout
@@ -1,3 +1,4 @@
+[
 {
   "x": [
     1,
@@ -9,3 +10,4 @@
     7
   ]
 }
+]
diff --git a/test/cases/dsl-json-collection-output/0015/expout b/test/cases/dsl-json-collection-output/0015/expout
index 5a7a2b420..519630862 100644
--- a/test/cases/dsl-json-collection-output/0015/expout
+++ b/test/cases/dsl-json-collection-output/0015/expout
@@ -1,3 +1,5 @@
+[
 {
   "x": {}
 }
+]
diff --git a/test/cases/dsl-json-collection-output/0016/expout b/test/cases/dsl-json-collection-output/0016/expout
index 12911b7b1..1b579c09b 100644
--- a/test/cases/dsl-json-collection-output/0016/expout
+++ b/test/cases/dsl-json-collection-output/0016/expout
@@ -1,3 +1,4 @@
+[
 {
   "x": {
     "a": 1,
@@ -5,3 +6,4 @@
     "c": 3
   }
 }
+]
diff --git a/test/cases/dsl-json-collection-output/0017/expout b/test/cases/dsl-json-collection-output/0017/expout
index 2ba2ad7fd..c7fa7112d 100644
--- a/test/cases/dsl-json-collection-output/0017/expout
+++ b/test/cases/dsl-json-collection-output/0017/expout
@@ -1,3 +1,4 @@
+[
 {
   "x": {
     "a": 1,
@@ -9,3 +10,4 @@
     "f": 6
   }
 }
+]
diff --git a/test/cases/dsl-json-collection-output/0018/expout b/test/cases/dsl-json-collection-output/0018/expout
index fcd98884f..9402c9cf1 100644
--- a/test/cases/dsl-json-collection-output/0018/expout
+++ b/test/cases/dsl-json-collection-output/0018/expout
@@ -1,4 +1,6 @@
+[
 {
   "x": {},
   "y": 1
 }
+]
diff --git a/test/cases/dsl-json-collection-output/0019/expout b/test/cases/dsl-json-collection-output/0019/expout
index 1d8b00211..cb2e6811e 100644
--- a/test/cases/dsl-json-collection-output/0019/expout
+++ b/test/cases/dsl-json-collection-output/0019/expout
@@ -1,3 +1,4 @@
+[
 {
   "x": {
     "a": 1,
@@ -6,3 +7,4 @@
   },
   "y": 4
 }
+]
diff --git a/test/cases/dsl-json-collection-output/0020/expout b/test/cases/dsl-json-collection-output/0020/expout
index 588ff2490..2aa17f9b2 100644
--- a/test/cases/dsl-json-collection-output/0020/expout
+++ b/test/cases/dsl-json-collection-output/0020/expout
@@ -1,3 +1,4 @@
+[
 {
   "x": {
     "a": 1,
@@ -10,3 +11,4 @@
   },
   "y": 7
 }
+]
diff --git a/test/cases/dsl-json-collection-output/0021/expout b/test/cases/dsl-json-collection-output/0021/expout
index e374c3da0..f23fb0eb5 100644
--- a/test/cases/dsl-json-collection-output/0021/expout
+++ b/test/cases/dsl-json-collection-output/0021/expout
@@ -1,3 +1,4 @@
+[
 {
   "x": [
     1,
@@ -9,3 +10,4 @@
     7
   ]
 }
+]
diff --git a/test/cases/dsl-json-collection-output/0022/expout b/test/cases/dsl-json-collection-output/0022/expout
index 9aa6ae1fb..441da11c7 100644
--- a/test/cases/dsl-json-collection-output/0022/expout
+++ b/test/cases/dsl-json-collection-output/0022/expout
@@ -1 +1,3 @@
+[
 {"x": [1, [2, [3, 4, 5], 6], 7]}
+]
diff --git a/test/cases/dsl-json-collection-output/0023/expout b/test/cases/dsl-json-collection-output/0023/expout
index 588ff2490..2aa17f9b2 100644
--- a/test/cases/dsl-json-collection-output/0023/expout
+++ b/test/cases/dsl-json-collection-output/0023/expout
@@ -1,3 +1,4 @@
+[
 {
   "x": {
     "a": 1,
@@ -10,3 +11,4 @@
   },
   "y": 7
 }
+]
diff --git a/test/cases/dsl-json-collection-output/0024/expout b/test/cases/dsl-json-collection-output/0024/expout
index 5ccde43b8..97c519aaf 100644
--- a/test/cases/dsl-json-collection-output/0024/expout
+++ b/test/cases/dsl-json-collection-output/0024/expout
@@ -1 +1,3 @@
+[
 {"x": {"a": 1, "b": {"c": 3, "d": 4, "e": 5}, "f": 6}, "y": 7}
+]
diff --git a/test/cases/dsl-json-parse-json-stringify/0001/expout b/test/cases/dsl-json-parse-json-stringify/0001/expout
index 261a409ed..8c341fcb7 100644
--- a/test/cases/dsl-json-parse-json-stringify/0001/expout
+++ b/test/cases/dsl-json-parse-json-stringify/0001/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -16,3 +17,4 @@
     "emtpy4": []
   }
 }
+]
diff --git a/test/cases/dsl-json-parse-json-stringify/0002/expout b/test/cases/dsl-json-parse-json-stringify/0002/expout
index 261a409ed..8c341fcb7 100644
--- a/test/cases/dsl-json-parse-json-stringify/0002/expout
+++ b/test/cases/dsl-json-parse-json-stringify/0002/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -16,3 +17,4 @@
     "emtpy4": []
   }
 }
+]
diff --git a/test/cases/dsl-json-parse-json-stringify/0003/expout b/test/cases/dsl-json-parse-json-stringify/0003/expout
index ee6ab25b8..3336298c7 100644
--- a/test/cases/dsl-json-parse-json-stringify/0003/expout
+++ b/test/cases/dsl-json-parse-json-stringify/0003/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -16,3 +17,4 @@
     "emtpy4": []
   }
 }
+]
diff --git a/test/cases/dsl-json-parse-json-stringify/0006/expout b/test/cases/dsl-json-parse-json-stringify/0006/expout
index 261a409ed..8c341fcb7 100644
--- a/test/cases/dsl-json-parse-json-stringify/0006/expout
+++ b/test/cases/dsl-json-parse-json-stringify/0006/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -16,3 +17,4 @@
     "emtpy4": []
   }
 }
+]
diff --git a/test/cases/dsl-json-parse-json-stringify/0007/expout b/test/cases/dsl-json-parse-json-stringify/0007/expout
index 0a3d2cfeb..9a45bc186 100644
--- a/test/cases/dsl-json-parse-json-stringify/0007/expout
+++ b/test/cases/dsl-json-parse-json-stringify/0007/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -25,3 +26,4 @@
     "emtpy4": []
   }
 }
+]
diff --git a/test/cases/dsl-lhs-indexing/0001/expout b/test/cases/dsl-lhs-indexing/0001/expout
index 61ea4c22a..fb581ccbf 100644
--- a/test/cases/dsl-lhs-indexing/0001/expout
+++ b/test/cases/dsl-lhs-indexing/0001/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -7,7 +8,7 @@
   "abc": {
     "test/input/2.dkvp": "def"
   }
-}
+},
 {
   "a": "eks",
   "b": "pan",
@@ -18,3 +19,4 @@
     "test/input/2.dkvp": "def"
   }
 }
+]
diff --git a/test/cases/dsl-lhs-indexing/0002/expout b/test/cases/dsl-lhs-indexing/0002/expout
index 706396711..f687c2a12 100644
--- a/test/cases/dsl-lhs-indexing/0002/expout
+++ b/test/cases/dsl-lhs-indexing/0002/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -7,7 +8,7 @@
   "abc": {
     "1": "def"
   }
-}
+},
 {
   "a": "eks",
   "b": "pan",
@@ -18,3 +19,4 @@
     "2": "def"
   }
 }
+]
diff --git a/test/cases/dsl-lhs-indexing/0003/expout b/test/cases/dsl-lhs-indexing/0003/expout
index 3c5a5f805..a6b654461 100644
--- a/test/cases/dsl-lhs-indexing/0003/expout
+++ b/test/cases/dsl-lhs-indexing/0003/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -9,7 +10,7 @@
       "1": "def"
     }
   }
-}
+},
 {
   "a": "eks",
   "b": "pan",
@@ -22,3 +23,4 @@
     }
   }
 }
+]
diff --git a/test/cases/dsl-lhs-indexing/0004/expout b/test/cases/dsl-lhs-indexing/0004/expout
index d140af1aa..c4676928a 100644
--- a/test/cases/dsl-lhs-indexing/0004/expout
+++ b/test/cases/dsl-lhs-indexing/0004/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -9,7 +10,7 @@
       "test/input/2.dkvp": "def"
     }
   }
-}
+},
 {
   "a": "eks",
   "b": "pan",
@@ -22,3 +23,4 @@
     }
   }
 }
+]
diff --git a/test/cases/dsl-lhs-indexing/0005/expout b/test/cases/dsl-lhs-indexing/0005/expout
index d18275273..39bcbdb70 100644
--- a/test/cases/dsl-lhs-indexing/0005/expout
+++ b/test/cases/dsl-lhs-indexing/0005/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -7,7 +8,7 @@
   "ghi": {
     "test/input/2.dkvp": "def"
   }
-}
+},
 {
   "a": "eks",
   "b": "pan",
@@ -18,3 +19,4 @@
     "test/input/2.dkvp": "def"
   }
 }
+]
diff --git a/test/cases/dsl-lhs-indexing/0006/expout b/test/cases/dsl-lhs-indexing/0006/expout
index 1c0dd7c14..c1802b67f 100644
--- a/test/cases/dsl-lhs-indexing/0006/expout
+++ b/test/cases/dsl-lhs-indexing/0006/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -7,7 +8,7 @@
   "ghi": {
     "1": "def"
   }
-}
+},
 {
   "a": "eks",
   "b": "pan",
@@ -19,3 +20,4 @@
     "2": "def"
   }
 }
+]
diff --git a/test/cases/dsl-lhs-indexing/0007/expout b/test/cases/dsl-lhs-indexing/0007/expout
index 432e919a7..f1e20a836 100644
--- a/test/cases/dsl-lhs-indexing/0007/expout
+++ b/test/cases/dsl-lhs-indexing/0007/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -9,7 +10,7 @@
       "1": "def"
     }
   }
-}
+},
 {
   "a": "eks",
   "b": "pan",
@@ -23,3 +24,4 @@
     }
   }
 }
+]
diff --git a/test/cases/dsl-lhs-indexing/0008/expout b/test/cases/dsl-lhs-indexing/0008/expout
index 34d0395c7..65716472d 100644
--- a/test/cases/dsl-lhs-indexing/0008/expout
+++ b/test/cases/dsl-lhs-indexing/0008/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -9,7 +10,7 @@
       "test/input/2.dkvp": "def"
     }
   }
-}
+},
 {
   "a": "eks",
   "b": "pan",
@@ -25,3 +26,4 @@
     }
   }
 }
+]
diff --git a/test/cases/dsl-lhs-indexing/0009/expout b/test/cases/dsl-lhs-indexing/0009/expout
index 029d9ff58..0a10835af 100644
--- a/test/cases/dsl-lhs-indexing/0009/expout
+++ b/test/cases/dsl-lhs-indexing/0009/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -5,7 +6,7 @@
   "x": 0.3467901443380824,
   "y": 0.7268028627434533,
   "new": 3
-}
+},
 {
   "a": "eks",
   "b": "pan",
@@ -14,3 +15,4 @@
   "y": 0.5221511083334797,
   "new": 3
 }
+]
diff --git a/test/cases/dsl-lhs-indexing/0010/expout b/test/cases/dsl-lhs-indexing/0010/expout
index d83d24b35..b67c83762 100644
--- a/test/cases/dsl-lhs-indexing/0010/expout
+++ b/test/cases/dsl-lhs-indexing/0010/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -5,7 +6,7 @@
   "x": 0.3467901443380824,
   "y": 0.7268028627434533,
   "new": [4]
-}
+},
 {
   "a": "eks",
   "b": "pan",
@@ -14,3 +15,4 @@
   "y": 0.5221511083334797,
   "new": [4]
 }
+]
diff --git a/test/cases/dsl-lhs-indexing/0011/expout b/test/cases/dsl-lhs-indexing/0011/expout
index d5398a6d1..25cc6384e 100644
--- a/test/cases/dsl-lhs-indexing/0011/expout
+++ b/test/cases/dsl-lhs-indexing/0011/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -7,7 +8,7 @@
   "new": [
     [5]
   ]
-}
+},
 {
   "a": "eks",
   "b": "pan",
@@ -18,3 +19,4 @@
     [5]
   ]
 }
+]
diff --git a/test/cases/dsl-lhs-indexing/0012/expout b/test/cases/dsl-lhs-indexing/0012/expout
index 92f5899a3..a32f78802 100644
--- a/test/cases/dsl-lhs-indexing/0012/expout
+++ b/test/cases/dsl-lhs-indexing/0012/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -7,7 +8,7 @@
   "new": {
     "x": 4
   }
-}
+},
 {
   "a": "eks",
   "b": "pan",
@@ -18,3 +19,4 @@
     "x": 4
   }
 }
+]
diff --git a/test/cases/dsl-lhs-indexing/0013/expout b/test/cases/dsl-lhs-indexing/0013/expout
index bdf8ad1da..56deaeb3d 100644
--- a/test/cases/dsl-lhs-indexing/0013/expout
+++ b/test/cases/dsl-lhs-indexing/0013/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -9,7 +10,7 @@
       "x": 5
     }
   }
-}
+},
 {
   "a": "eks",
   "b": "pan",
@@ -22,3 +23,4 @@
     }
   }
 }
+]
diff --git a/test/cases/dsl-local-map-variable-write-read/0001/expout b/test/cases/dsl-local-map-variable-write-read/0001/expout
index 0bb0cb89d..daaa1862e 100644
--- a/test/cases/dsl-local-map-variable-write-read/0001/expout
+++ b/test/cases/dsl-local-map-variable-write-read/0001/expout
@@ -1,5 +1,7 @@
+[
 {
   "x": 3,
   "y": 4,
   "z": 5
 }
+]
diff --git a/test/cases/dsl-local-map-variable-write-read/0002/expout b/test/cases/dsl-local-map-variable-write-read/0002/expout
index 63112115f..f6cbca8f5 100644
--- a/test/cases/dsl-local-map-variable-write-read/0002/expout
+++ b/test/cases/dsl-local-map-variable-write-read/0002/expout
@@ -1,6 +1,8 @@
+[
 {
   "x": 3,
   "y": 4,
   "z": 5,
   "d": 9
 }
+]
diff --git a/test/cases/dsl-local-map-variable-write-read/0003/expout b/test/cases/dsl-local-map-variable-write-read/0003/expout
index 3f952a16a..97de0ae8e 100644
--- a/test/cases/dsl-local-map-variable-write-read/0003/expout
+++ b/test/cases/dsl-local-map-variable-write-read/0003/expout
@@ -1,3 +1,4 @@
+[
 {
   "x": 3,
   "y": 4,
@@ -7,3 +8,4 @@
   "c": 8,
   "d": 9
 }
+]
diff --git a/test/cases/dsl-local-map-variable-write-read/0004/expout b/test/cases/dsl-local-map-variable-write-read/0004/expout
index d61aa1c96..86e2adb21 100644
--- a/test/cases/dsl-local-map-variable-write-read/0004/expout
+++ b/test/cases/dsl-local-map-variable-write-read/0004/expout
@@ -1,3 +1,4 @@
+[
 {
   "x": 3,
   "y": 4,
@@ -39,3 +40,4 @@
   },
   "d3": 9
 }
+]
diff --git a/test/cases/dsl-map-dot/0001/expout b/test/cases/dsl-map-dot/0001/expout
index dc5a33a9e..97190722b 100644
--- a/test/cases/dsl-map-dot/0001/expout
+++ b/test/cases/dsl-map-dot/0001/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -26,3 +27,4 @@
   },
   "zzzzzzz": "bar.baz"
 }
+]
diff --git a/test/cases/dsl-map-dot/0002/expout b/test/cases/dsl-map-dot/0002/expout
index 0a3d2cfeb..9a45bc186 100644
--- a/test/cases/dsl-map-dot/0002/expout
+++ b/test/cases/dsl-map-dot/0002/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -25,3 +26,4 @@
     "emtpy4": []
   }
 }
+]
diff --git a/test/cases/dsl-map-dot/0003/expout b/test/cases/dsl-map-dot/0003/expout
index 0a3d2cfeb..9a45bc186 100644
--- a/test/cases/dsl-map-dot/0003/expout
+++ b/test/cases/dsl-map-dot/0003/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -25,3 +26,4 @@
     "emtpy4": []
   }
 }
+]
diff --git a/test/cases/dsl-map-dot/0004/expout b/test/cases/dsl-map-dot/0004/expout
index 0a3d2cfeb..9a45bc186 100644
--- a/test/cases/dsl-map-dot/0004/expout
+++ b/test/cases/dsl-map-dot/0004/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -25,3 +26,4 @@
     "emtpy4": []
   }
 }
+]
diff --git a/test/cases/dsl-mapsum-mapdiff-mapexcept/0031/expout b/test/cases/dsl-mapsum-mapdiff-mapexcept/0031/expout
index fb00a1235..223d78bef 100644
--- a/test/cases/dsl-mapsum-mapdiff-mapexcept/0031/expout
+++ b/test/cases/dsl-mapsum-mapdiff-mapexcept/0031/expout
@@ -1,3 +1,4 @@
+[
 {
   "x": "a.b.c.d.e.f",
   "y": {
@@ -14,3 +15,4 @@
     "5": "e"
   }
 }
+]
diff --git a/test/cases/dsl-mapsum-mapdiff-mapexcept/0032/expout b/test/cases/dsl-mapsum-mapdiff-mapexcept/0032/expout
index f396ade1a..aa8a0c11d 100644
--- a/test/cases/dsl-mapsum-mapdiff-mapexcept/0032/expout
+++ b/test/cases/dsl-mapsum-mapdiff-mapexcept/0032/expout
@@ -1,3 +1,4 @@
+[
 {
   "x": "a.b.c.d.e.f",
   "y": {
@@ -14,3 +15,4 @@
     "6": "f"
   }
 }
+]
diff --git a/test/cases/dsl-min-max-types/0001/expout b/test/cases/dsl-min-max-types/0001/expout
index e021b5638..14596fcab 100644
--- a/test/cases/dsl-min-max-types/0001/expout
+++ b/test/cases/dsl-min-max-types/0001/expout
@@ -1,3 +1,4 @@
+[
 {
   "n": 1,
   "b": "true",
@@ -30,3 +31,4 @@
     }
   }
 }
+]
diff --git a/test/cases/dsl-min-max-types/0002/expout b/test/cases/dsl-min-max-types/0002/expout
index 4c4057af9..e7734b7f8 100644
--- a/test/cases/dsl-min-max-types/0002/expout
+++ b/test/cases/dsl-min-max-types/0002/expout
@@ -1,3 +1,4 @@
+[
 {
   "n": 1,
   "b": "true",
@@ -30,3 +31,4 @@
     }
   }
 }
+]
diff --git a/test/cases/dsl-min-max-types/0003/expout b/test/cases/dsl-min-max-types/0003/expout
index bd0cd7c8f..0358168ad 100644
--- a/test/cases/dsl-min-max-types/0003/expout
+++ b/test/cases/dsl-min-max-types/0003/expout
@@ -1,3 +1,4 @@
+[
 {
   "n": 1,
   "b": "true",
@@ -30,3 +31,4 @@
     }
   }
 }
+]
diff --git a/test/cases/dsl-min-max-types/0004/expout b/test/cases/dsl-min-max-types/0004/expout
index 2e62305c0..7360c4803 100644
--- a/test/cases/dsl-min-max-types/0004/expout
+++ b/test/cases/dsl-min-max-types/0004/expout
@@ -1,3 +1,4 @@
+[
 {
   "n": 1,
   "b": "true",
@@ -30,3 +31,4 @@
     }
   }
 }
+]
diff --git a/test/cases/dsl-multi-index/0001/expout b/test/cases/dsl-multi-index/0001/expout
index 3351d4940..7860c784e 100644
--- a/test/cases/dsl-multi-index/0001/expout
+++ b/test/cases/dsl-multi-index/0001/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -12,3 +13,4 @@
     }
   }
 }
+]
diff --git a/test/cases/dsl-multi-index/0002/expout b/test/cases/dsl-multi-index/0002/expout
index 95add0e5b..3b4abf0c4 100644
--- a/test/cases/dsl-multi-index/0002/expout
+++ b/test/cases/dsl-multi-index/0002/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -28,3 +29,4 @@
     }
   }
 }
+]
diff --git a/test/cases/dsl-output-redirects/0070/expout b/test/cases/dsl-output-redirects/0070/expout
index 4dabad497..bae02cb77 100644
--- a/test/cases/dsl-output-redirects/0070/expout
+++ b/test/cases/dsl-output-redirects/0070/expout
@@ -1,33 +1,35 @@
+[
 {
   "x": 1
-}
+},
 {
   "x": 2
-}
+},
 {
   "x": 3
-}
+},
 {
   "x": 4
-}
+},
 {
   "x": 5
-}
+},
 {
   "x": 6
-}
+},
 {
   "x": 7
-}
+},
 {
   "x": 8
-}
+},
 {
   "x": 9
-}
+},
 {
   "x": 10
 }
+]
 a   b   i  x                   y
 pan pan 1  0.3467901443380824  0.7268028627434533
 eks pan 2  0.7586799647899636  0.5221511083334797
diff --git a/test/cases/dsl-output-redirects/0071/expout b/test/cases/dsl-output-redirects/0071/expout
index eed189aad..4a1435f7c 100644
--- a/test/cases/dsl-output-redirects/0071/expout
+++ b/test/cases/dsl-output-redirects/0071/expout
@@ -9,3 +9,5 @@ x
 8
 9
 10
+[
+]
diff --git a/test/cases/dsl-redirects/0004/out.expect b/test/cases/dsl-redirects/0004/out.expect
index 686f30737..a619474e4 100644
--- a/test/cases/dsl-redirects/0004/out.expect
+++ b/test/cases/dsl-redirects/0004/out.expect
@@ -1,66 +1,67 @@
+[
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": "eks",
   "b": "pan",
   "i": 2,
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
-}
+},
 {
   "a": "wye",
   "b": "wye",
   "i": 3,
   "x": 0.20460330576630303,
   "y": 0.33831852551664776
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "i": 4,
   "x": 0.38139939387114097,
   "y": 0.13418874328430463
-}
+},
 {
   "a": "wye",
   "b": "pan",
   "i": 5,
   "x": 0.5732889198020006,
   "y": 0.8636244699032729
-}
+},
 {
   "a": "zee",
   "b": "pan",
   "i": 6,
   "x": 0.5271261600918548,
   "y": 0.49322128674835697
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "i": 7,
   "x": 0.6117840605678454,
   "y": 0.1878849191181694
-}
+},
 {
   "a": "zee",
   "b": "wye",
   "i": 8,
   "x": 0.5985540091064224,
   "y": 0.976181385699006
-}
+},
 {
   "a": "hat",
   "b": "wye",
   "i": 9,
   "x": 0.03144187646093577,
   "y": 0.7495507603507059
-}
+},
 {
   "a": "pan",
   "b": "wye",
@@ -68,3 +69,4 @@
   "x": 0.5026260055412137,
   "y": 0.9526183602969864
 }
+]
diff --git a/test/cases/dsl-redirects/0008/out.eks.expect b/test/cases/dsl-redirects/0008/out.eks.expect
index 15bea4cda..a8c805a6c 100644
--- a/test/cases/dsl-redirects/0008/out.eks.expect
+++ b/test/cases/dsl-redirects/0008/out.eks.expect
@@ -1,17 +1,18 @@
+[
 {
   "a": "eks",
   "b": "pan",
   "i": 2,
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "i": 4,
   "x": 0.38139939387114097,
   "y": 0.13418874328430463
-}
+},
 {
   "a": "eks",
   "b": "zee",
@@ -19,3 +20,4 @@
   "x": 0.6117840605678454,
   "y": 0.1878849191181694
 }
+]
diff --git a/test/cases/dsl-redirects/0008/out.hat.expect b/test/cases/dsl-redirects/0008/out.hat.expect
index 0e5f371e1..26a3cc201 100644
--- a/test/cases/dsl-redirects/0008/out.hat.expect
+++ b/test/cases/dsl-redirects/0008/out.hat.expect
@@ -1,3 +1,4 @@
+[
 {
   "a": "hat",
   "b": "wye",
@@ -5,3 +6,4 @@
   "x": 0.03144187646093577,
   "y": 0.7495507603507059
 }
+]
diff --git a/test/cases/dsl-redirects/0008/out.pan.expect b/test/cases/dsl-redirects/0008/out.pan.expect
index c3e2a9136..6091369cf 100644
--- a/test/cases/dsl-redirects/0008/out.pan.expect
+++ b/test/cases/dsl-redirects/0008/out.pan.expect
@@ -1,10 +1,11 @@
+[
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": "pan",
   "b": "wye",
@@ -12,3 +13,4 @@
   "x": 0.5026260055412137,
   "y": 0.9526183602969864
 }
+]
diff --git a/test/cases/dsl-redirects/0008/out.wye.expect b/test/cases/dsl-redirects/0008/out.wye.expect
index 41b1a0a07..f5b6c8516 100644
--- a/test/cases/dsl-redirects/0008/out.wye.expect
+++ b/test/cases/dsl-redirects/0008/out.wye.expect
@@ -1,10 +1,11 @@
+[
 {
   "a": "wye",
   "b": "wye",
   "i": 3,
   "x": 0.20460330576630303,
   "y": 0.33831852551664776
-}
+},
 {
   "a": "wye",
   "b": "pan",
@@ -12,3 +13,4 @@
   "x": 0.5732889198020006,
   "y": 0.8636244699032729
 }
+]
diff --git a/test/cases/dsl-redirects/0008/out.zee.expect b/test/cases/dsl-redirects/0008/out.zee.expect
index 314184c2e..c4b4ba966 100644
--- a/test/cases/dsl-redirects/0008/out.zee.expect
+++ b/test/cases/dsl-redirects/0008/out.zee.expect
@@ -1,10 +1,11 @@
+[
 {
   "a": "zee",
   "b": "pan",
   "i": 6,
   "x": 0.5271261600918548,
   "y": 0.49322128674835697
-}
+},
 {
   "a": "zee",
   "b": "wye",
@@ -12,3 +13,4 @@
   "x": 0.5985540091064224,
   "y": 0.976181385699006
 }
+]
diff --git a/test/cases/dsl-redirects/0010/expout b/test/cases/dsl-redirects/0010/expout
index 78843db6d..7b1db2d6b 100644
--- a/test/cases/dsl-redirects/0010/expout
+++ b/test/cases/dsl-redirects/0010/expout
@@ -1,66 +1,67 @@
+[
 {
   "A": "PAN",
   "B": "PAN",
   "I": 1,
   "X": 0.3467901443380824,
   "Y": 0.7268028627434533
-}
+},
 {
   "A": "EKS",
   "B": "PAN",
   "I": 2,
   "X": 0.7586799647899636,
   "Y": 0.5221511083334797
-}
+},
 {
   "A": "WYE",
   "B": "WYE",
   "I": 3,
   "X": 0.20460330576630303,
   "Y": 0.33831852551664776
-}
+},
 {
   "A": "EKS",
   "B": "WYE",
   "I": 4,
   "X": 0.38139939387114097,
   "Y": 0.13418874328430463
-}
+},
 {
   "A": "WYE",
   "B": "PAN",
   "I": 5,
   "X": 0.5732889198020006,
   "Y": 0.8636244699032729
-}
+},
 {
   "A": "ZEE",
   "B": "PAN",
   "I": 6,
   "X": 0.5271261600918548,
   "Y": 0.49322128674835697
-}
+},
 {
   "A": "EKS",
   "B": "ZEE",
   "I": 7,
   "X": 0.6117840605678454,
   "Y": 0.1878849191181694
-}
+},
 {
   "A": "ZEE",
   "B": "WYE",
   "I": 8,
   "X": 0.5985540091064224,
   "Y": 0.976181385699006
-}
+},
 {
   "A": "HAT",
   "B": "WYE",
   "I": 9,
   "X": 0.03144187646093577,
   "Y": 0.7495507603507059
-}
+},
 {
   "A": "PAN",
   "B": "WYE",
@@ -68,3 +69,4 @@
   "X": 0.5026260055412137,
   "Y": 0.9526183602969864
 }
+]
diff --git a/test/cases/dsl-redirects/0034/out.ekspan.expect b/test/cases/dsl-redirects/0034/out.ekspan.expect
index 84bf17984..271660a9d 100644
--- a/test/cases/dsl-redirects/0034/out.ekspan.expect
+++ b/test/cases/dsl-redirects/0034/out.ekspan.expect
@@ -1,4 +1,6 @@
+[
 {
   "a": "eks",
   "b": "pan"
 }
+]
diff --git a/test/cases/dsl-redirects/0034/out.ekswye.expect b/test/cases/dsl-redirects/0034/out.ekswye.expect
index 11a3a5b33..e5100cd78 100644
--- a/test/cases/dsl-redirects/0034/out.ekswye.expect
+++ b/test/cases/dsl-redirects/0034/out.ekswye.expect
@@ -1,4 +1,6 @@
+[
 {
   "a": "eks",
   "b": "wye"
 }
+]
diff --git a/test/cases/dsl-redirects/0034/out.ekszee.expect b/test/cases/dsl-redirects/0034/out.ekszee.expect
index 043f2aca6..dff12c54d 100644
--- a/test/cases/dsl-redirects/0034/out.ekszee.expect
+++ b/test/cases/dsl-redirects/0034/out.ekszee.expect
@@ -1,4 +1,6 @@
+[
 {
   "a": "eks",
   "b": "zee"
 }
+]
diff --git a/test/cases/dsl-redirects/0034/out.hatwye.expect b/test/cases/dsl-redirects/0034/out.hatwye.expect
index 39a94a163..3ff68ff25 100644
--- a/test/cases/dsl-redirects/0034/out.hatwye.expect
+++ b/test/cases/dsl-redirects/0034/out.hatwye.expect
@@ -1,4 +1,6 @@
+[
 {
   "a": "hat",
   "b": "wye"
 }
+]
diff --git a/test/cases/dsl-redirects/0034/out.panpan.expect b/test/cases/dsl-redirects/0034/out.panpan.expect
index a9a33a8ca..3f46b7a7d 100644
--- a/test/cases/dsl-redirects/0034/out.panpan.expect
+++ b/test/cases/dsl-redirects/0034/out.panpan.expect
@@ -1,4 +1,6 @@
+[
 {
   "a": "pan",
   "b": "pan"
 }
+]
diff --git a/test/cases/dsl-redirects/0034/out.panwye.expect b/test/cases/dsl-redirects/0034/out.panwye.expect
index 88ec8dbf8..d5baf3561 100644
--- a/test/cases/dsl-redirects/0034/out.panwye.expect
+++ b/test/cases/dsl-redirects/0034/out.panwye.expect
@@ -1,4 +1,6 @@
+[
 {
   "a": "pan",
   "b": "wye"
 }
+]
diff --git a/test/cases/dsl-redirects/0034/out.wyepan.expect b/test/cases/dsl-redirects/0034/out.wyepan.expect
index 48bb11f47..60fd56b5d 100644
--- a/test/cases/dsl-redirects/0034/out.wyepan.expect
+++ b/test/cases/dsl-redirects/0034/out.wyepan.expect
@@ -1,4 +1,6 @@
+[
 {
   "a": "wye",
   "b": "pan"
 }
+]
diff --git a/test/cases/dsl-redirects/0034/out.wyewye.expect b/test/cases/dsl-redirects/0034/out.wyewye.expect
index bd252b8ed..07d9720fe 100644
--- a/test/cases/dsl-redirects/0034/out.wyewye.expect
+++ b/test/cases/dsl-redirects/0034/out.wyewye.expect
@@ -1,4 +1,6 @@
+[
 {
   "a": "wye",
   "b": "wye"
 }
+]
diff --git a/test/cases/dsl-redirects/0034/out.zeepan.expect b/test/cases/dsl-redirects/0034/out.zeepan.expect
index 046a25d34..240a5041f 100644
--- a/test/cases/dsl-redirects/0034/out.zeepan.expect
+++ b/test/cases/dsl-redirects/0034/out.zeepan.expect
@@ -1,4 +1,6 @@
+[
 {
   "a": "zee",
   "b": "pan"
 }
+]
diff --git a/test/cases/dsl-redirects/0034/out.zeewye.expect b/test/cases/dsl-redirects/0034/out.zeewye.expect
index 81ffac364..91b1c2fb2 100644
--- a/test/cases/dsl-redirects/0034/out.zeewye.expect
+++ b/test/cases/dsl-redirects/0034/out.zeewye.expect
@@ -1,4 +1,6 @@
+[
 {
   "a": "zee",
   "b": "wye"
 }
+]
diff --git a/test/cases/dsl-redirects/0041/out.ekspan.expect b/test/cases/dsl-redirects/0041/out.ekspan.expect
index 090e8b834..c2f4d3203 100644
--- a/test/cases/dsl-redirects/0041/out.ekspan.expect
+++ b/test/cases/dsl-redirects/0041/out.ekspan.expect
@@ -1,6 +1,8 @@
+[
 {
   "a": {
     "1": "pan",
     "2": "eks"
   }
 }
+]
diff --git a/test/cases/dsl-redirects/0041/out.ekswye.expect b/test/cases/dsl-redirects/0041/out.ekswye.expect
index 92175d461..f67bc65ef 100644
--- a/test/cases/dsl-redirects/0041/out.ekswye.expect
+++ b/test/cases/dsl-redirects/0041/out.ekswye.expect
@@ -1,3 +1,4 @@
+[
 {
   "a": {
     "1": "pan",
@@ -6,3 +7,4 @@
     "4": "eks"
   }
 }
+]
diff --git a/test/cases/dsl-redirects/0041/out.panpan.expect b/test/cases/dsl-redirects/0041/out.panpan.expect
index cb11ebef3..33d10af82 100644
--- a/test/cases/dsl-redirects/0041/out.panpan.expect
+++ b/test/cases/dsl-redirects/0041/out.panpan.expect
@@ -1,5 +1,7 @@
+[
 {
   "a": {
     "1": "pan"
   }
 }
+]
diff --git a/test/cases/dsl-redirects/0041/out.wyewye.expect b/test/cases/dsl-redirects/0041/out.wyewye.expect
index 0646812c2..bd330c621 100644
--- a/test/cases/dsl-redirects/0041/out.wyewye.expect
+++ b/test/cases/dsl-redirects/0041/out.wyewye.expect
@@ -1,3 +1,4 @@
+[
 {
   "a": {
     "1": "pan",
@@ -5,3 +6,4 @@
     "3": "wye"
   }
 }
+]
diff --git a/test/cases/dsl-redirects/0048/out.ekspan.expect b/test/cases/dsl-redirects/0048/out.ekspan.expect
index e14d1dd96..eabaf51e3 100644
--- a/test/cases/dsl-redirects/0048/out.ekspan.expect
+++ b/test/cases/dsl-redirects/0048/out.ekspan.expect
@@ -1,8 +1,10 @@
+[
 {
   "NR": "1",
   "a": "pan"
-}
+},
 {
   "NR": "2",
   "a": "eks"
 }
+]
diff --git a/test/cases/dsl-redirects/0048/out.ekswye.expect b/test/cases/dsl-redirects/0048/out.ekswye.expect
index f42069628..4238b3f97 100644
--- a/test/cases/dsl-redirects/0048/out.ekswye.expect
+++ b/test/cases/dsl-redirects/0048/out.ekswye.expect
@@ -1,16 +1,18 @@
+[
 {
   "NR": "1",
   "a": "pan"
-}
+},
 {
   "NR": "2",
   "a": "eks"
-}
+},
 {
   "NR": "3",
   "a": "wye"
-}
+},
 {
   "NR": "4",
   "a": "eks"
 }
+]
diff --git a/test/cases/dsl-redirects/0048/out.panpan.expect b/test/cases/dsl-redirects/0048/out.panpan.expect
index abb16200b..1be78080b 100644
--- a/test/cases/dsl-redirects/0048/out.panpan.expect
+++ b/test/cases/dsl-redirects/0048/out.panpan.expect
@@ -1,4 +1,6 @@
+[
 {
   "NR": "1",
   "a": "pan"
 }
+]
diff --git a/test/cases/dsl-redirects/0048/out.wyewye.expect b/test/cases/dsl-redirects/0048/out.wyewye.expect
index bcdb2320e..4a87add81 100644
--- a/test/cases/dsl-redirects/0048/out.wyewye.expect
+++ b/test/cases/dsl-redirects/0048/out.wyewye.expect
@@ -1,12 +1,14 @@
+[
 {
   "NR": "1",
   "a": "pan"
-}
+},
 {
   "NR": "2",
   "a": "eks"
-}
+},
 {
   "NR": "3",
   "a": "wye"
 }
+]
diff --git a/test/cases/dsl-redirects/0055/out.ekspan.expect b/test/cases/dsl-redirects/0055/out.ekspan.expect
index 4f21e0bd2..a0371e348 100644
--- a/test/cases/dsl-redirects/0055/out.ekspan.expect
+++ b/test/cases/dsl-redirects/0055/out.ekspan.expect
@@ -1,3 +1,4 @@
+[
 {
   "a": {
     "1": "pan",
@@ -8,3 +9,4 @@
     "2": "pan"
   }
 }
+]
diff --git a/test/cases/dsl-redirects/0055/out.ekswye.expect b/test/cases/dsl-redirects/0055/out.ekswye.expect
index 0cf91be66..90686cf11 100644
--- a/test/cases/dsl-redirects/0055/out.ekswye.expect
+++ b/test/cases/dsl-redirects/0055/out.ekswye.expect
@@ -1,3 +1,4 @@
+[
 {
   "a": {
     "1": "pan",
@@ -12,3 +13,4 @@
     "4": "wye"
   }
 }
+]
diff --git a/test/cases/dsl-redirects/0055/out.panpan.expect b/test/cases/dsl-redirects/0055/out.panpan.expect
index f80a444f2..29d4d91c4 100644
--- a/test/cases/dsl-redirects/0055/out.panpan.expect
+++ b/test/cases/dsl-redirects/0055/out.panpan.expect
@@ -1,3 +1,4 @@
+[
 {
   "a": {
     "1": "pan"
@@ -6,3 +7,4 @@
     "1": "pan"
   }
 }
+]
diff --git a/test/cases/dsl-redirects/0055/out.wyewye.expect b/test/cases/dsl-redirects/0055/out.wyewye.expect
index da0a8f63a..c5a5e2cde 100644
--- a/test/cases/dsl-redirects/0055/out.wyewye.expect
+++ b/test/cases/dsl-redirects/0055/out.wyewye.expect
@@ -1,3 +1,4 @@
+[
 {
   "a": {
     "1": "pan",
@@ -10,3 +11,4 @@
     "3": "wye"
   }
 }
+]
diff --git a/test/cases/dsl-redirects/0062/out.ekspan.expect b/test/cases/dsl-redirects/0062/out.ekspan.expect
index 8ec52d9d9..e2e139753 100644
--- a/test/cases/dsl-redirects/0062/out.ekspan.expect
+++ b/test/cases/dsl-redirects/0062/out.ekspan.expect
@@ -1,10 +1,12 @@
+[
 {
   "NR": "1",
   "a": "pan",
   "b": "pan"
-}
+},
 {
   "NR": "2",
   "a": "eks",
   "b": "pan"
 }
+]
diff --git a/test/cases/dsl-redirects/0062/out.ekswye.expect b/test/cases/dsl-redirects/0062/out.ekswye.expect
index 06402858a..6bbd24633 100644
--- a/test/cases/dsl-redirects/0062/out.ekswye.expect
+++ b/test/cases/dsl-redirects/0062/out.ekswye.expect
@@ -1,20 +1,22 @@
+[
 {
   "NR": "1",
   "a": "pan",
   "b": "pan"
-}
+},
 {
   "NR": "2",
   "a": "eks",
   "b": "pan"
-}
+},
 {
   "NR": "3",
   "a": "wye",
   "b": "wye"
-}
+},
 {
   "NR": "4",
   "a": "eks",
   "b": "wye"
 }
+]
diff --git a/test/cases/dsl-redirects/0062/out.panpan.expect b/test/cases/dsl-redirects/0062/out.panpan.expect
index ec288c741..129cd2e65 100644
--- a/test/cases/dsl-redirects/0062/out.panpan.expect
+++ b/test/cases/dsl-redirects/0062/out.panpan.expect
@@ -1,5 +1,7 @@
+[
 {
   "NR": "1",
   "a": "pan",
   "b": "pan"
 }
+]
diff --git a/test/cases/dsl-redirects/0062/out.wyewye.expect b/test/cases/dsl-redirects/0062/out.wyewye.expect
index 38586c01d..f294d3e75 100644
--- a/test/cases/dsl-redirects/0062/out.wyewye.expect
+++ b/test/cases/dsl-redirects/0062/out.wyewye.expect
@@ -1,15 +1,17 @@
+[
 {
   "NR": "1",
   "a": "pan",
   "b": "pan"
-}
+},
 {
   "NR": "2",
   "a": "eks",
   "b": "pan"
-}
+},
 {
   "NR": "3",
   "a": "wye",
   "b": "wye"
 }
+]
diff --git a/test/cases/dsl-redirects/0085/out.ekspan.expect b/test/cases/dsl-redirects/0085/out.ekspan.expect
index c45cf6b5b..92739b09f 100644
--- a/test/cases/dsl-redirects/0085/out.ekspan.expect
+++ b/test/cases/dsl-redirects/0085/out.ekspan.expect
@@ -1,4 +1,6 @@
+[
 {
   "1": "pan",
   "2": "eks"
 }
+]
diff --git a/test/cases/dsl-redirects/0085/out.ekswye.expect b/test/cases/dsl-redirects/0085/out.ekswye.expect
index 23d7188cc..841d52a38 100644
--- a/test/cases/dsl-redirects/0085/out.ekswye.expect
+++ b/test/cases/dsl-redirects/0085/out.ekswye.expect
@@ -1,6 +1,8 @@
+[
 {
   "1": "pan",
   "2": "eks",
   "3": "wye",
   "4": "eks"
 }
+]
diff --git a/test/cases/dsl-redirects/0085/out.panpan.expect b/test/cases/dsl-redirects/0085/out.panpan.expect
index cfe6b4f9f..1ce916d49 100644
--- a/test/cases/dsl-redirects/0085/out.panpan.expect
+++ b/test/cases/dsl-redirects/0085/out.panpan.expect
@@ -1,3 +1,5 @@
+[
 {
   "1": "pan"
 }
+]
diff --git a/test/cases/dsl-redirects/0085/out.wyewye.expect b/test/cases/dsl-redirects/0085/out.wyewye.expect
index fdecb986b..0c1dec8f3 100644
--- a/test/cases/dsl-redirects/0085/out.wyewye.expect
+++ b/test/cases/dsl-redirects/0085/out.wyewye.expect
@@ -1,5 +1,7 @@
+[
 {
   "1": "pan",
   "2": "eks",
   "3": "wye"
 }
+]
diff --git a/test/cases/dsl-redirects/0106/out.ekspan.expect b/test/cases/dsl-redirects/0106/out.ekspan.expect
index 8ec52d9d9..e2e139753 100644
--- a/test/cases/dsl-redirects/0106/out.ekspan.expect
+++ b/test/cases/dsl-redirects/0106/out.ekspan.expect
@@ -1,10 +1,12 @@
+[
 {
   "NR": "1",
   "a": "pan",
   "b": "pan"
-}
+},
 {
   "NR": "2",
   "a": "eks",
   "b": "pan"
 }
+]
diff --git a/test/cases/dsl-redirects/0106/out.ekswye.expect b/test/cases/dsl-redirects/0106/out.ekswye.expect
index 06402858a..6bbd24633 100644
--- a/test/cases/dsl-redirects/0106/out.ekswye.expect
+++ b/test/cases/dsl-redirects/0106/out.ekswye.expect
@@ -1,20 +1,22 @@
+[
 {
   "NR": "1",
   "a": "pan",
   "b": "pan"
-}
+},
 {
   "NR": "2",
   "a": "eks",
   "b": "pan"
-}
+},
 {
   "NR": "3",
   "a": "wye",
   "b": "wye"
-}
+},
 {
   "NR": "4",
   "a": "eks",
   "b": "wye"
 }
+]
diff --git a/test/cases/dsl-redirects/0106/out.panpan.expect b/test/cases/dsl-redirects/0106/out.panpan.expect
index ec288c741..129cd2e65 100644
--- a/test/cases/dsl-redirects/0106/out.panpan.expect
+++ b/test/cases/dsl-redirects/0106/out.panpan.expect
@@ -1,5 +1,7 @@
+[
 {
   "NR": "1",
   "a": "pan",
   "b": "pan"
 }
+]
diff --git a/test/cases/dsl-redirects/0106/out.wyewye.expect b/test/cases/dsl-redirects/0106/out.wyewye.expect
index 38586c01d..f294d3e75 100644
--- a/test/cases/dsl-redirects/0106/out.wyewye.expect
+++ b/test/cases/dsl-redirects/0106/out.wyewye.expect
@@ -1,15 +1,17 @@
+[
 {
   "NR": "1",
   "a": "pan",
   "b": "pan"
-}
+},
 {
   "NR": "2",
   "a": "eks",
   "b": "pan"
-}
+},
 {
   "NR": "3",
   "a": "wye",
   "b": "wye"
 }
+]
diff --git a/test/cases/dsl-short-circuit/0028/expout b/test/cases/dsl-short-circuit/0028/expout
index df7cb4e77..88c75d40a 100644
--- a/test/cases/dsl-short-circuit/0028/expout
+++ b/test/cases/dsl-short-circuit/0028/expout
@@ -1,13 +1,14 @@
+[
 {
   "a": 1,
   "b": 2,
   "c": 3
-}
+},
 {
   "a": "",
   "b": "fillb",
   "c": 3
-}
+},
 {
   "x": 7,
   "y": 8,
@@ -15,3 +16,4 @@
   "a": "filla",
   "b": "fillb"
 }
+]
diff --git a/test/cases/dsl-slice/0001/expout b/test/cases/dsl-slice/0001/expout
index 4275b009c..1548e37f3 100644
--- a/test/cases/dsl-slice/0001/expout
+++ b/test/cases/dsl-slice/0001/expout
@@ -1,66 +1,68 @@
+[
 {
   "a35": [3, 4, 5]
-}
+},
 {
   "a37": [3, 4, 5, 6, 7]
-}
+},
 {
   "a17": [1, 2, 3, 4, 5, 6, 7]
-}
+},
 {
   "a07": [1, 2, 3, 4, 5, 6, 7]
-}
+},
 {
   "a39": [3, 4, 5, 6, 7]
-}
+},
 {
   "a53": []
-}
+},
 {
   "a93": []
-}
+},
 {
   "m11": (error)
-}
+},
 {
   "s35": "cde"
-}
+},
 {
   "s37": "cdefg"
-}
+},
 {
   "s17": "abcdefg"
-}
+},
 {
   "s07": ""
-}
+},
 {
   "s39": ""
-}
+},
 {
   "s53": ""
-}
+},
 {
   "s93": ""
-}
+},
 {
   "u35": "def"
-}
+},
 {
   "u37": ""
-}
+},
 {
   "u17": ""
-}
+},
 {
   "u07": ""
-}
+},
 {
   "u39": ""
-}
+},
 {
   "u53": ""
-}
+},
 {
   "u93": ""
 }
+]
diff --git a/test/cases/dsl-slice/0002/expout b/test/cases/dsl-slice/0002/expout
index 36553cfb7..607127bb8 100644
--- a/test/cases/dsl-slice/0002/expout
+++ b/test/cases/dsl-slice/0002/expout
@@ -1,33 +1,35 @@
+[
 {
   "ax0": []
-}
+},
 {
   "ax1": [1]
-}
+},
 {
   "ax5": [1, 2, 3, 4, 5]
-}
+},
 {
   "ax7": [1, 2, 3, 4, 5, 6, 7]
-}
+},
 {
   "ax9": [1, 2, 3, 4, 5, 6, 7]
-}
+},
 {
   "mx1": (error)
-}
+},
 {
   "sx0": ""
-}
+},
 {
   "sx1": "a"
-}
+},
 {
   "sx5": "abcde"
-}
+},
 {
   "sx7": "abcdefg"
-}
+},
 {
   "sx9": ""
 }
+]
diff --git a/test/cases/dsl-slice/0003/expout b/test/cases/dsl-slice/0003/expout
index a55a86f61..624f4235c 100644
--- a/test/cases/dsl-slice/0003/expout
+++ b/test/cases/dsl-slice/0003/expout
@@ -1,33 +1,35 @@
+[
 {
   "a0x": [1, 2, 3, 4, 5, 6, 7]
-}
+},
 {
   "a1x": [1, 2, 3, 4, 5, 6, 7]
-}
+},
 {
   "a5x": [5, 6, 7]
-}
+},
 {
   "a7x": [7]
-}
+},
 {
   "a9x": []
-}
+},
 {
   "m1x": (error)
-}
+},
 {
   "s0x": ""
-}
+},
 {
   "s1x": "abcdefg"
-}
+},
 {
   "s5x": "efg"
-}
+},
 {
   "s7x": "g"
-}
+},
 {
   "s9x": ""
 }
+]
diff --git a/test/cases/dsl-sorts/sorta/expout b/test/cases/dsl-sorts/sorta/expout
index 7b3995275..8cdb07f28 100644
--- a/test/cases/dsl-sorts/sorta/expout
+++ b/test/cases/dsl-sorts/sorta/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": 6,
   "b": 5,
@@ -10,7 +11,7 @@
   "lexdown": [6, 5, 4],
   "foldup": [4, 5, 6],
   "folddown": [6, 5, 4]
-}
+},
 {
   "a": 2,
   "b": 10,
@@ -23,7 +24,7 @@
   "lexdown": [2, 10, 1],
   "foldup": [1, 10, 2],
   "folddown": [2, 10, 1]
-}
+},
 {
   "a": "apple",
   "b": "Ball",
@@ -37,3 +38,4 @@
   "foldup": ["apple", "Ball", "cat"],
   "folddown": ["cat", "Ball", "apple"]
 }
+]
diff --git a/test/cases/dsl-sorts/sortaf-within/expout b/test/cases/dsl-sorts/sortaf-within/expout
index 621e49ad9..104daff1f 100644
--- a/test/cases/dsl-sorts/sortaf-within/expout
+++ b/test/cases/dsl-sorts/sortaf-within/expout
@@ -1,3 +1,4 @@
+[
 {
   "key": "alpha",
   "values": "5;2;8;6;1;4;9;10;3;7",
@@ -5,3 +6,4 @@
   "reverse": [10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
   "even_then_odd": [2, 4, 6, 8, 10, 1, 3, 5, 7, 9]
 }
+]
diff --git a/test/cases/dsl-sorts/sortmf-within/expout b/test/cases/dsl-sorts/sortmf-within/expout
index acb15cce5..c683738c5 100644
--- a/test/cases/dsl-sorts/sortmf-within/expout
+++ b/test/cases/dsl-sorts/sortmf-within/expout
@@ -18,3 +18,5 @@
   "b": 2,
   "c": 1
 }
+[
+]
diff --git a/test/cases/dsl-sorts/sortmk/expout b/test/cases/dsl-sorts/sortmk/expout
index f03e7c246..da52f95c1 100644
--- a/test/cases/dsl-sorts/sortmk/expout
+++ b/test/cases/dsl-sorts/sortmk/expout
@@ -1,3 +1,4 @@
+[
 {
   "map": {
     "6": 1,
@@ -44,7 +45,7 @@
     "5": 2,
     "4": 3
   }
-}
+},
 {
   "map": {
     "2": 1,
@@ -91,7 +92,7 @@
     "10": 2,
     "1": 3
   }
-}
+},
 {
   "map": {
     "apple": 1,
@@ -139,3 +140,4 @@
     "apple": 1
   }
 }
+]
diff --git a/test/cases/dsl-split-join/0023/expout b/test/cases/dsl-split-join/0023/expout
index 713ab6e70..2f1b7d33a 100644
--- a/test/cases/dsl-split-join/0023/expout
+++ b/test/cases/dsl-split-join/0023/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -5,7 +6,7 @@
   "x": 0.3467901443380824,
   "y": 0.7268028627434533,
   "keys": ["a", "b", "i", "x", "y"]
-}
+},
 {
   "a": "eks",
   "b": "pan",
@@ -13,7 +14,7 @@
   "x": 0.7586799647899636,
   "y": 0.5221511083334797,
   "keys": ["a", "b", "i", "x", "y"]
-}
+},
 {
   "a": "wye",
   "b": "wye",
@@ -21,7 +22,7 @@
   "x": 0.20460330576630303,
   "y": 0.33831852551664776,
   "keys": ["a", "b", "i", "x", "y"]
-}
+},
 {
   "a": "eks",
   "b": "wye",
@@ -30,3 +31,4 @@
   "y": 0.13418874328430463,
   "keys": ["a", "b", "i", "x", "y"]
 }
+]
diff --git a/test/cases/dsl-split-join/0024/expout b/test/cases/dsl-split-join/0024/expout
index faa6755e0..365b4dbfa 100644
--- a/test/cases/dsl-split-join/0024/expout
+++ b/test/cases/dsl-split-join/0024/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -5,7 +6,7 @@
   "x": 0.3467901443380824,
   "y": 0.7268028627434533,
   "values": ["pan", "pan", 1, 0.3467901443380824, 0.7268028627434533]
-}
+},
 {
   "a": "eks",
   "b": "pan",
@@ -13,7 +14,7 @@
   "x": 0.7586799647899636,
   "y": 0.5221511083334797,
   "values": ["eks", "pan", 2, 0.7586799647899636, 0.5221511083334797]
-}
+},
 {
   "a": "wye",
   "b": "wye",
@@ -21,7 +22,7 @@
   "x": 0.20460330576630303,
   "y": 0.33831852551664776,
   "values": ["wye", "wye", 3, 0.20460330576630303, 0.33831852551664776]
-}
+},
 {
   "a": "eks",
   "b": "wye",
@@ -30,3 +31,4 @@
   "y": 0.13418874328430463,
   "values": ["eks", "wye", 4, 0.38139939387114097, 0.13418874328430463]
 }
+]
diff --git a/test/cases/dsl-split-join/0025/expout b/test/cases/dsl-split-join/0025/expout
index c603654fa..46183de4a 100644
--- a/test/cases/dsl-split-join/0025/expout
+++ b/test/cases/dsl-split-join/0025/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -5,7 +6,7 @@
   "x": 0.3467901443380824,
   "y": 0.7268028627434533,
   "keys": [1, 2, 3]
-}
+},
 {
   "a": "eks",
   "b": "pan",
@@ -13,7 +14,7 @@
   "x": 0.7586799647899636,
   "y": 0.5221511083334797,
   "keys": [1, 2, 3]
-}
+},
 {
   "a": "wye",
   "b": "wye",
@@ -21,7 +22,7 @@
   "x": 0.20460330576630303,
   "y": 0.33831852551664776,
   "keys": [1, 2, 3]
-}
+},
 {
   "a": "eks",
   "b": "wye",
@@ -30,3 +31,4 @@
   "y": 0.13418874328430463,
   "keys": [1, 2, 3]
 }
+]
diff --git a/test/cases/dsl-split-join/0026/expout b/test/cases/dsl-split-join/0026/expout
index 385c29221..2c70b899b 100644
--- a/test/cases/dsl-split-join/0026/expout
+++ b/test/cases/dsl-split-join/0026/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -5,7 +6,7 @@
   "x": 0.3467901443380824,
   "y": 0.7268028627434533,
   "values": [7, 8, 9]
-}
+},
 {
   "a": "eks",
   "b": "pan",
@@ -13,7 +14,7 @@
   "x": 0.7586799647899636,
   "y": 0.5221511083334797,
   "values": [7, 8, 9]
-}
+},
 {
   "a": "wye",
   "b": "wye",
@@ -21,7 +22,7 @@
   "x": 0.20460330576630303,
   "y": 0.33831852551664776,
   "values": [7, 8, 9]
-}
+},
 {
   "a": "eks",
   "b": "wye",
@@ -30,3 +31,4 @@
   "y": 0.13418874328430463,
   "values": [7, 8, 9]
 }
+]
diff --git a/test/cases/dsl-split-join/0027/expout b/test/cases/dsl-split-join/0027/expout
index 9cae02b65..21db560be 100644
--- a/test/cases/dsl-split-join/0027/expout
+++ b/test/cases/dsl-split-join/0027/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -5,7 +6,7 @@
   "x": 0.3467901443380824,
   "y": 0.7268028627434533,
   "v": [1]
-}
+},
 {
   "a": "eks",
   "b": "pan",
@@ -13,7 +14,7 @@
   "x": 0.7586799647899636,
   "y": 0.5221511083334797,
   "v": [1, 2]
-}
+},
 {
   "a": "wye",
   "b": "wye",
@@ -21,7 +22,7 @@
   "x": 0.20460330576630303,
   "y": 0.33831852551664776,
   "v": [1, 2, 3]
-}
+},
 {
   "a": "eks",
   "b": "wye",
@@ -30,3 +31,4 @@
   "y": 0.13418874328430463,
   "v": [1, 2, 3, 4]
 }
+]
diff --git a/test/cases/dsl-user-defined-functions-and-subroutines/0031/expout b/test/cases/dsl-user-defined-functions-and-subroutines/0031/expout
index 3f94f4ee0..b2b5c1c7d 100644
--- a/test/cases/dsl-user-defined-functions-and-subroutines/0031/expout
+++ b/test/cases/dsl-user-defined-functions-and-subroutines/0031/expout
@@ -1,85 +1,87 @@
+[
 {
   "ell": 1
-}
+},
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": "eks",
   "b": "pan",
   "i": 2,
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
-}
+},
 {
   "a": "wye",
   "b": "wye",
   "i": 3,
   "x": 0.20460330576630303,
   "y": 0.33831852551664776
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "i": 4,
   "x": 0.38139939387114097,
   "y": 0.13418874328430463
-}
+},
 {
   "a": "wye",
   "b": "pan",
   "i": 5,
   "x": 0.5732889198020006,
   "y": 0.8636244699032729
-}
+},
 {
   "a": "zee",
   "b": "pan",
   "i": 6,
   "x": 0.5271261600918548,
   "y": 0.49322128674835697
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "i": 7,
   "x": 0.6117840605678454,
   "y": 0.1878849191181694
-}
+},
 {
   "a": "zee",
   "b": "wye",
   "i": 8,
   "x": 0.5985540091064224,
   "y": 0.976181385699006
-}
+},
 {
   "a": "hat",
   "b": "wye",
   "i": 9,
   "x": 0.03144187646093577,
   "y": 0.7495507603507059
-}
+},
 {
   "a": "pan",
   "b": "wye",
   "i": 10,
   "x": 0.5026260055412137,
   "y": 0.9526183602969864
-}
+},
 {
   "a": 10
-}
+},
 {
   "emm": 2
-}
+},
 {
   "b": 20
-}
+},
 {
   "c": 30
 }
+]
diff --git a/test/cases/dsl-whitespace/0001/expout b/test/cases/dsl-whitespace/0001/expout
index 25acdb419..811bea05d 100644
--- a/test/cases/dsl-whitespace/0001/expout
+++ b/test/cases/dsl-whitespace/0001/expout
@@ -1,4 +1,6 @@
+[
 {
   "x": " a     b ",
   "y": "a     b"
 }
+]
diff --git a/test/cases/dsl-whitespace/0002/expout b/test/cases/dsl-whitespace/0002/expout
index 8c45b2ca0..1b975a071 100644
--- a/test/cases/dsl-whitespace/0002/expout
+++ b/test/cases/dsl-whitespace/0002/expout
@@ -1,4 +1,6 @@
+[
 {
   "x": " a     b ",
   "y": "a     b "
 }
+]
diff --git a/test/cases/dsl-whitespace/0003/expout b/test/cases/dsl-whitespace/0003/expout
index 428fa929b..c0b18e657 100644
--- a/test/cases/dsl-whitespace/0003/expout
+++ b/test/cases/dsl-whitespace/0003/expout
@@ -1,4 +1,6 @@
+[
 {
   "x": " a     b ",
   "y": " a     b"
 }
+]
diff --git a/test/cases/dsl-whitespace/0004/expout b/test/cases/dsl-whitespace/0004/expout
index e061da4c8..067bd328b 100644
--- a/test/cases/dsl-whitespace/0004/expout
+++ b/test/cases/dsl-whitespace/0004/expout
@@ -1,4 +1,6 @@
+[
 {
   "x": " a     b ",
   "y": " a b "
 }
+]
diff --git a/test/cases/dsl-whitespace/0005/expout b/test/cases/dsl-whitespace/0005/expout
index 72cb6d40a..d531244b2 100644
--- a/test/cases/dsl-whitespace/0005/expout
+++ b/test/cases/dsl-whitespace/0005/expout
@@ -1,4 +1,6 @@
+[
 {
   "x": " a     b ",
   "y": "a b"
 }
+]
diff --git a/test/cases/io-dedupe-field-names/csv-no-dedupe/expout b/test/cases/io-dedupe-field-names/csv-no-dedupe/expout
index c403e0f33..6937b48cd 100644
--- a/test/cases/io-dedupe-field-names/csv-no-dedupe/expout
+++ b/test/cases/io-dedupe-field-names/csv-no-dedupe/expout
@@ -1,5 +1,7 @@
+[
 {
   "a": 1,
   "b": 5,
   "c": 4
 }
+]
diff --git a/test/cases/io-dedupe-field-names/csv/expout b/test/cases/io-dedupe-field-names/csv/expout
index d688c7b6d..e50ad7d37 100644
--- a/test/cases/io-dedupe-field-names/csv/expout
+++ b/test/cases/io-dedupe-field-names/csv/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": 1,
   "b": 2,
@@ -5,3 +6,4 @@
   "c": 4,
   "b_3": 5
 }
+]
diff --git a/test/cases/io-dedupe-field-names/csvlite-no-dedupe/expout b/test/cases/io-dedupe-field-names/csvlite-no-dedupe/expout
index c403e0f33..6937b48cd 100644
--- a/test/cases/io-dedupe-field-names/csvlite-no-dedupe/expout
+++ b/test/cases/io-dedupe-field-names/csvlite-no-dedupe/expout
@@ -1,5 +1,7 @@
+[
 {
   "a": 1,
   "b": 5,
   "c": 4
 }
+]
diff --git a/test/cases/io-dedupe-field-names/csvlite/expout b/test/cases/io-dedupe-field-names/csvlite/expout
index d688c7b6d..e50ad7d37 100644
--- a/test/cases/io-dedupe-field-names/csvlite/expout
+++ b/test/cases/io-dedupe-field-names/csvlite/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": 1,
   "b": 2,
@@ -5,3 +6,4 @@
   "c": 4,
   "b_3": 5
 }
+]
diff --git a/test/cases/io-dedupe-field-names/dkvp-no-dedupe/expout b/test/cases/io-dedupe-field-names/dkvp-no-dedupe/expout
index c403e0f33..6937b48cd 100644
--- a/test/cases/io-dedupe-field-names/dkvp-no-dedupe/expout
+++ b/test/cases/io-dedupe-field-names/dkvp-no-dedupe/expout
@@ -1,5 +1,7 @@
+[
 {
   "a": 1,
   "b": 5,
   "c": 4
 }
+]
diff --git a/test/cases/io-dedupe-field-names/dkvp/expout b/test/cases/io-dedupe-field-names/dkvp/expout
index d688c7b6d..e50ad7d37 100644
--- a/test/cases/io-dedupe-field-names/dkvp/expout
+++ b/test/cases/io-dedupe-field-names/dkvp/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": 1,
   "b": 2,
@@ -5,3 +6,4 @@
   "c": 4,
   "b_3": 5
 }
+]
diff --git a/test/cases/io-dedupe-field-names/json-no-dedupe/expout b/test/cases/io-dedupe-field-names/json-no-dedupe/expout
index c403e0f33..6937b48cd 100644
--- a/test/cases/io-dedupe-field-names/json-no-dedupe/expout
+++ b/test/cases/io-dedupe-field-names/json-no-dedupe/expout
@@ -1,5 +1,7 @@
+[
 {
   "a": 1,
   "b": 5,
   "c": 4
 }
+]
diff --git a/test/cases/io-dedupe-field-names/json/expout b/test/cases/io-dedupe-field-names/json/expout
index c403e0f33..6937b48cd 100644
--- a/test/cases/io-dedupe-field-names/json/expout
+++ b/test/cases/io-dedupe-field-names/json/expout
@@ -1,5 +1,7 @@
+[
 {
   "a": 1,
   "b": 5,
   "c": 4
 }
+]
diff --git a/test/cases/io-dedupe-field-names/nidx-no-dedupe/expout b/test/cases/io-dedupe-field-names/nidx-no-dedupe/expout
index dac3aa847..4f84291dc 100644
--- a/test/cases/io-dedupe-field-names/nidx-no-dedupe/expout
+++ b/test/cases/io-dedupe-field-names/nidx-no-dedupe/expout
@@ -1,3 +1,4 @@
+[
 {
   "1": 1,
   "2": 2,
@@ -5,3 +6,4 @@
   "4": 4,
   "5": 5
 }
+]
diff --git a/test/cases/io-dedupe-field-names/nidx/expout b/test/cases/io-dedupe-field-names/nidx/expout
index dac3aa847..4f84291dc 100644
--- a/test/cases/io-dedupe-field-names/nidx/expout
+++ b/test/cases/io-dedupe-field-names/nidx/expout
@@ -1,3 +1,4 @@
+[
 {
   "1": 1,
   "2": 2,
@@ -5,3 +6,4 @@
   "4": 4,
   "5": 5
 }
+]
diff --git a/test/cases/io-dedupe-field-names/pprint-no-dedupe/expout b/test/cases/io-dedupe-field-names/pprint-no-dedupe/expout
index c403e0f33..6937b48cd 100644
--- a/test/cases/io-dedupe-field-names/pprint-no-dedupe/expout
+++ b/test/cases/io-dedupe-field-names/pprint-no-dedupe/expout
@@ -1,5 +1,7 @@
+[
 {
   "a": 1,
   "b": 5,
   "c": 4
 }
+]
diff --git a/test/cases/io-dedupe-field-names/pprint/expout b/test/cases/io-dedupe-field-names/pprint/expout
index d688c7b6d..e50ad7d37 100644
--- a/test/cases/io-dedupe-field-names/pprint/expout
+++ b/test/cases/io-dedupe-field-names/pprint/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": 1,
   "b": 2,
@@ -5,3 +6,4 @@
   "c": 4,
   "b_3": 5
 }
+]
diff --git a/test/cases/io-dedupe-field-names/xtab-no-dedupe/expout b/test/cases/io-dedupe-field-names/xtab-no-dedupe/expout
index c403e0f33..6937b48cd 100644
--- a/test/cases/io-dedupe-field-names/xtab-no-dedupe/expout
+++ b/test/cases/io-dedupe-field-names/xtab-no-dedupe/expout
@@ -1,5 +1,7 @@
+[
 {
   "a": 1,
   "b": 5,
   "c": 4
 }
+]
diff --git a/test/cases/io-dedupe-field-names/xtab/expout b/test/cases/io-dedupe-field-names/xtab/expout
index d688c7b6d..e50ad7d37 100644
--- a/test/cases/io-dedupe-field-names/xtab/expout
+++ b/test/cases/io-dedupe-field-names/xtab/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": 1,
   "b": 2,
@@ -5,3 +6,4 @@
   "c": 4,
   "b_3": 5
 }
+]
diff --git a/test/cases/io-format-conversion-keystroke-savers/0003/expout b/test/cases/io-format-conversion-keystroke-savers/0003/expout
index 686f30737..a619474e4 100644
--- a/test/cases/io-format-conversion-keystroke-savers/0003/expout
+++ b/test/cases/io-format-conversion-keystroke-savers/0003/expout
@@ -1,66 +1,67 @@
+[
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": "eks",
   "b": "pan",
   "i": 2,
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
-}
+},
 {
   "a": "wye",
   "b": "wye",
   "i": 3,
   "x": 0.20460330576630303,
   "y": 0.33831852551664776
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "i": 4,
   "x": 0.38139939387114097,
   "y": 0.13418874328430463
-}
+},
 {
   "a": "wye",
   "b": "pan",
   "i": 5,
   "x": 0.5732889198020006,
   "y": 0.8636244699032729
-}
+},
 {
   "a": "zee",
   "b": "pan",
   "i": 6,
   "x": 0.5271261600918548,
   "y": 0.49322128674835697
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "i": 7,
   "x": 0.6117840605678454,
   "y": 0.1878849191181694
-}
+},
 {
   "a": "zee",
   "b": "wye",
   "i": 8,
   "x": 0.5985540091064224,
   "y": 0.976181385699006
-}
+},
 {
   "a": "hat",
   "b": "wye",
   "i": 9,
   "x": 0.03144187646093577,
   "y": 0.7495507603507059
-}
+},
 {
   "a": "pan",
   "b": "wye",
@@ -68,3 +69,4 @@
   "x": 0.5026260055412137,
   "y": 0.9526183602969864
 }
+]
diff --git a/test/cases/io-format-conversion-keystroke-savers/0010/expout b/test/cases/io-format-conversion-keystroke-savers/0010/expout
index 686f30737..a619474e4 100644
--- a/test/cases/io-format-conversion-keystroke-savers/0010/expout
+++ b/test/cases/io-format-conversion-keystroke-savers/0010/expout
@@ -1,66 +1,67 @@
+[
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": "eks",
   "b": "pan",
   "i": 2,
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
-}
+},
 {
   "a": "wye",
   "b": "wye",
   "i": 3,
   "x": 0.20460330576630303,
   "y": 0.33831852551664776
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "i": 4,
   "x": 0.38139939387114097,
   "y": 0.13418874328430463
-}
+},
 {
   "a": "wye",
   "b": "pan",
   "i": 5,
   "x": 0.5732889198020006,
   "y": 0.8636244699032729
-}
+},
 {
   "a": "zee",
   "b": "pan",
   "i": 6,
   "x": 0.5271261600918548,
   "y": 0.49322128674835697
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "i": 7,
   "x": 0.6117840605678454,
   "y": 0.1878849191181694
-}
+},
 {
   "a": "zee",
   "b": "wye",
   "i": 8,
   "x": 0.5985540091064224,
   "y": 0.976181385699006
-}
+},
 {
   "a": "hat",
   "b": "wye",
   "i": 9,
   "x": 0.03144187646093577,
   "y": 0.7495507603507059
-}
+},
 {
   "a": "pan",
   "b": "wye",
@@ -68,3 +69,4 @@
   "x": 0.5026260055412137,
   "y": 0.9526183602969864
 }
+]
diff --git a/test/cases/io-format-conversion-keystroke-savers/0017/expout b/test/cases/io-format-conversion-keystroke-savers/0017/expout
index 686f30737..a619474e4 100644
--- a/test/cases/io-format-conversion-keystroke-savers/0017/expout
+++ b/test/cases/io-format-conversion-keystroke-savers/0017/expout
@@ -1,66 +1,67 @@
+[
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": "eks",
   "b": "pan",
   "i": 2,
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
-}
+},
 {
   "a": "wye",
   "b": "wye",
   "i": 3,
   "x": 0.20460330576630303,
   "y": 0.33831852551664776
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "i": 4,
   "x": 0.38139939387114097,
   "y": 0.13418874328430463
-}
+},
 {
   "a": "wye",
   "b": "pan",
   "i": 5,
   "x": 0.5732889198020006,
   "y": 0.8636244699032729
-}
+},
 {
   "a": "zee",
   "b": "pan",
   "i": 6,
   "x": 0.5271261600918548,
   "y": 0.49322128674835697
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "i": 7,
   "x": 0.6117840605678454,
   "y": 0.1878849191181694
-}
+},
 {
   "a": "zee",
   "b": "wye",
   "i": 8,
   "x": 0.5985540091064224,
   "y": 0.976181385699006
-}
+},
 {
   "a": "hat",
   "b": "wye",
   "i": 9,
   "x": 0.03144187646093577,
   "y": 0.7495507603507059
-}
+},
 {
   "a": "pan",
   "b": "wye",
@@ -68,3 +69,4 @@
   "x": 0.5026260055412137,
   "y": 0.9526183602969864
 }
+]
diff --git a/test/cases/io-format-conversion-keystroke-savers/0024/expout b/test/cases/io-format-conversion-keystroke-savers/0024/expout
index 726d26b59..8ee72e77f 100644
--- a/test/cases/io-format-conversion-keystroke-savers/0024/expout
+++ b/test/cases/io-format-conversion-keystroke-savers/0024/expout
@@ -1,66 +1,67 @@
+[
 {
   "1": "pan",
   "2": "pan",
   "3": 1,
   "4": 0.3467901443380824,
   "5": 0.7268028627434533
-}
+},
 {
   "1": "eks",
   "2": "pan",
   "3": 2,
   "4": 0.7586799647899636,
   "5": 0.5221511083334797
-}
+},
 {
   "1": "wye",
   "2": "wye",
   "3": 3,
   "4": 0.20460330576630303,
   "5": 0.33831852551664776
-}
+},
 {
   "1": "eks",
   "2": "wye",
   "3": 4,
   "4": 0.38139939387114097,
   "5": 0.13418874328430463
-}
+},
 {
   "1": "wye",
   "2": "pan",
   "3": 5,
   "4": 0.5732889198020006,
   "5": 0.8636244699032729
-}
+},
 {
   "1": "zee",
   "2": "pan",
   "3": 6,
   "4": 0.5271261600918548,
   "5": 0.49322128674835697
-}
+},
 {
   "1": "eks",
   "2": "zee",
   "3": 7,
   "4": 0.6117840605678454,
   "5": 0.1878849191181694
-}
+},
 {
   "1": "zee",
   "2": "wye",
   "3": 8,
   "4": 0.5985540091064224,
   "5": 0.976181385699006
-}
+},
 {
   "1": "hat",
   "2": "wye",
   "3": 9,
   "4": 0.03144187646093577,
   "5": 0.7495507603507059
-}
+},
 {
   "1": "pan",
   "2": "wye",
@@ -68,3 +69,4 @@
   "4": 0.5026260055412137,
   "5": 0.9526183602969864
 }
+]
diff --git a/test/cases/io-format-conversion-keystroke-savers/0039/expout b/test/cases/io-format-conversion-keystroke-savers/0039/expout
index 686f30737..a619474e4 100644
--- a/test/cases/io-format-conversion-keystroke-savers/0039/expout
+++ b/test/cases/io-format-conversion-keystroke-savers/0039/expout
@@ -1,66 +1,67 @@
+[
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": "eks",
   "b": "pan",
   "i": 2,
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
-}
+},
 {
   "a": "wye",
   "b": "wye",
   "i": 3,
   "x": 0.20460330576630303,
   "y": 0.33831852551664776
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "i": 4,
   "x": 0.38139939387114097,
   "y": 0.13418874328430463
-}
+},
 {
   "a": "wye",
   "b": "pan",
   "i": 5,
   "x": 0.5732889198020006,
   "y": 0.8636244699032729
-}
+},
 {
   "a": "zee",
   "b": "pan",
   "i": 6,
   "x": 0.5271261600918548,
   "y": 0.49322128674835697
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "i": 7,
   "x": 0.6117840605678454,
   "y": 0.1878849191181694
-}
+},
 {
   "a": "zee",
   "b": "wye",
   "i": 8,
   "x": 0.5985540091064224,
   "y": 0.976181385699006
-}
+},
 {
   "a": "hat",
   "b": "wye",
   "i": 9,
   "x": 0.03144187646093577,
   "y": 0.7495507603507059
-}
+},
 {
   "a": "pan",
   "b": "wye",
@@ -68,3 +69,4 @@
   "x": 0.5026260055412137,
   "y": 0.9526183602969864
 }
+]
diff --git a/test/cases/io-format-conversion-keystroke-savers/0046/expout b/test/cases/io-format-conversion-keystroke-savers/0046/expout
index 686f30737..a619474e4 100644
--- a/test/cases/io-format-conversion-keystroke-savers/0046/expout
+++ b/test/cases/io-format-conversion-keystroke-savers/0046/expout
@@ -1,66 +1,67 @@
+[
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": "eks",
   "b": "pan",
   "i": 2,
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
-}
+},
 {
   "a": "wye",
   "b": "wye",
   "i": 3,
   "x": 0.20460330576630303,
   "y": 0.33831852551664776
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "i": 4,
   "x": 0.38139939387114097,
   "y": 0.13418874328430463
-}
+},
 {
   "a": "wye",
   "b": "pan",
   "i": 5,
   "x": 0.5732889198020006,
   "y": 0.8636244699032729
-}
+},
 {
   "a": "zee",
   "b": "pan",
   "i": 6,
   "x": 0.5271261600918548,
   "y": 0.49322128674835697
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "i": 7,
   "x": 0.6117840605678454,
   "y": 0.1878849191181694
-}
+},
 {
   "a": "zee",
   "b": "wye",
   "i": 8,
   "x": 0.5985540091064224,
   "y": 0.976181385699006
-}
+},
 {
   "a": "hat",
   "b": "wye",
   "i": 9,
   "x": 0.03144187646093577,
   "y": 0.7495507603507059
-}
+},
 {
   "a": "pan",
   "b": "wye",
@@ -68,3 +69,4 @@
   "x": 0.5026260055412137,
   "y": 0.9526183602969864
 }
+]
diff --git a/test/cases/io-format-conversion-keystroke-savers/0051/expout b/test/cases/io-format-conversion-keystroke-savers/0051/expout
index 686f30737..a619474e4 100644
--- a/test/cases/io-format-conversion-keystroke-savers/0051/expout
+++ b/test/cases/io-format-conversion-keystroke-savers/0051/expout
@@ -1,66 +1,67 @@
+[
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": "eks",
   "b": "pan",
   "i": 2,
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
-}
+},
 {
   "a": "wye",
   "b": "wye",
   "i": 3,
   "x": 0.20460330576630303,
   "y": 0.33831852551664776
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "i": 4,
   "x": 0.38139939387114097,
   "y": 0.13418874328430463
-}
+},
 {
   "a": "wye",
   "b": "pan",
   "i": 5,
   "x": 0.5732889198020006,
   "y": 0.8636244699032729
-}
+},
 {
   "a": "zee",
   "b": "pan",
   "i": 6,
   "x": 0.5271261600918548,
   "y": 0.49322128674835697
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "i": 7,
   "x": 0.6117840605678454,
   "y": 0.1878849191181694
-}
+},
 {
   "a": "zee",
   "b": "wye",
   "i": 8,
   "x": 0.5985540091064224,
   "y": 0.976181385699006
-}
+},
 {
   "a": "hat",
   "b": "wye",
   "i": 9,
   "x": 0.03144187646093577,
   "y": 0.7495507603507059
-}
+},
 {
   "a": "pan",
   "b": "wye",
@@ -68,3 +69,4 @@
   "x": 0.5026260055412137,
   "y": 0.9526183602969864
 }
+]
diff --git a/test/cases/io-ixs-regex/0001/expout b/test/cases/io-ixs-regex/0001/expout
index acfc0f71c..8c8bda43a 100644
--- a/test/cases/io-ixs-regex/0001/expout
+++ b/test/cases/io-ixs-regex/0001/expout
@@ -1,10 +1,12 @@
+[
 {
   "1": "a",
   "2": "b",
   "3": "c"
-}
+},
 {
   "1": 1,
   "2": 2,
   "3": 3
 }
+]
diff --git a/test/cases/io-ixs-regex/0002/expout b/test/cases/io-ixs-regex/0002/expout
index acfc0f71c..8c8bda43a 100644
--- a/test/cases/io-ixs-regex/0002/expout
+++ b/test/cases/io-ixs-regex/0002/expout
@@ -1,10 +1,12 @@
+[
 {
   "1": "a",
   "2": "b",
   "3": "c"
-}
+},
 {
   "1": 1,
   "2": 2,
   "3": 3
 }
+]
diff --git a/test/cases/io-json-io/0004/expout b/test/cases/io-json-io/0004/expout
index 331599995..0f3c7db9e 100644
--- a/test/cases/io-json-io/0004/expout
+++ b/test/cases/io-json-io/0004/expout
@@ -1,12 +1,14 @@
+[
 {
   "a": 1,
   "b": "x",
   "c": 3
-}
+},
 {
   "d": 4
-}
+},
 {
   "1": 5,
   "f": 6
 }
+]
diff --git a/test/cases/io-json-io/0005/cmd b/test/cases/io-json-io/0005/cmd
index e6a27135d..f085429ce 100644
--- a/test/cases/io-json-io/0005/cmd
+++ b/test/cases/io-json-io/0005/cmd
@@ -1 +1 @@
-mlr --ojson --jvstack cat test/input/json-output-options.dkvp
+mlr --ojson --no-jvstack cat test/input/json-output-options.dkvp
diff --git a/test/cases/io-json-io/0005/expout b/test/cases/io-json-io/0005/expout
index 331599995..11813fa70 100644
--- a/test/cases/io-json-io/0005/expout
+++ b/test/cases/io-json-io/0005/expout
@@ -1,12 +1,5 @@
-{
-  "a": 1,
-  "b": "x",
-  "c": 3
-}
-{
-  "d": 4
-}
-{
-  "1": 5,
-  "f": 6
-}
+[
+{"a": 1, "b": "x", "c": 3},
+{"d": 4},
+{"1": 5, "f": 6}
+]
diff --git a/test/cases/io-json-io/0006/cmd b/test/cases/io-json-io/0006/cmd
deleted file mode 100644
index 6a986d50f..000000000
--- a/test/cases/io-json-io/0006/cmd
+++ /dev/null
@@ -1 +0,0 @@
-mlr --ojson --jlistwrap cat test/input/json-output-options.dkvp
diff --git a/test/cases/io-json-io/0006/expout b/test/cases/io-json-io/0006/expout
deleted file mode 100644
index 0f3c7db9e..000000000
--- a/test/cases/io-json-io/0006/expout
+++ /dev/null
@@ -1,14 +0,0 @@
-[
-{
-  "a": 1,
-  "b": "x",
-  "c": 3
-},
-{
-  "d": 4
-},
-{
-  "1": 5,
-  "f": 6
-}
-]
diff --git a/test/cases/io-json-io/0007/cmd b/test/cases/io-json-io/0007/cmd
deleted file mode 100644
index 698862853..000000000
--- a/test/cases/io-json-io/0007/cmd
+++ /dev/null
@@ -1 +0,0 @@
-mlr --ojson --jvstack --jlistwrap cat test/input/json-output-options.dkvp
diff --git a/test/cases/io-json-io/0007/expout b/test/cases/io-json-io/0007/expout
deleted file mode 100644
index 0f3c7db9e..000000000
--- a/test/cases/io-json-io/0007/expout
+++ /dev/null
@@ -1,14 +0,0 @@
-[
-{
-  "a": 1,
-  "b": "x",
-  "c": 3
-},
-{
-  "d": 4
-},
-{
-  "1": 5,
-  "f": 6
-}
-]
diff --git a/test/cases/io-json-io/0008/cmd b/test/cases/io-json-io/0008/cmd
deleted file mode 100644
index 7e0d874da..000000000
--- a/test/cases/io-json-io/0008/cmd
+++ /dev/null
@@ -1 +0,0 @@
-mlr --ojson --jquoteall cat test/input/json-output-options.dkvp
diff --git a/test/cases/io-json-io/0009/cmd b/test/cases/io-json-io/0009/cmd
deleted file mode 100644
index b77d2bf21..000000000
--- a/test/cases/io-json-io/0009/cmd
+++ /dev/null
@@ -1 +0,0 @@
-mlr --ojson --jvstack --jquoteall cat test/input/json-output-options.dkvp
diff --git a/test/cases/io-json-io/0009/expout b/test/cases/io-json-io/0009/expout
deleted file mode 100644
index 331599995..000000000
--- a/test/cases/io-json-io/0009/expout
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "a": 1,
-  "b": "x",
-  "c": 3
-}
-{
-  "d": 4
-}
-{
-  "1": 5,
-  "f": 6
-}
diff --git a/test/cases/io-json-io/0010/cmd b/test/cases/io-json-io/0010/cmd
deleted file mode 100644
index ecbd663e9..000000000
--- a/test/cases/io-json-io/0010/cmd
+++ /dev/null
@@ -1 +0,0 @@
-mlr --ojson --jlistwrap --jquoteall cat test/input/json-output-options.dkvp
diff --git a/test/cases/io-json-io/0010/expout b/test/cases/io-json-io/0010/expout
deleted file mode 100644
index 0f3c7db9e..000000000
--- a/test/cases/io-json-io/0010/expout
+++ /dev/null
@@ -1,14 +0,0 @@
-[
-{
-  "a": 1,
-  "b": "x",
-  "c": 3
-},
-{
-  "d": 4
-},
-{
-  "1": 5,
-  "f": 6
-}
-]
diff --git a/test/cases/io-json-io/0011/cmd b/test/cases/io-json-io/0011/cmd
index a2b962447..7e0d874da 100644
--- a/test/cases/io-json-io/0011/cmd
+++ b/test/cases/io-json-io/0011/cmd
@@ -1 +1 @@
-mlr --ojson --jvstack --jlistwrap --jquoteall cat test/input/json-output-options.dkvp
+mlr --ojson --jquoteall cat test/input/json-output-options.dkvp
diff --git a/test/cases/io-json-io/0012/cmd b/test/cases/io-json-io/0012/cmd
deleted file mode 100644
index fdd20334f..000000000
--- a/test/cases/io-json-io/0012/cmd
+++ /dev/null
@@ -1 +0,0 @@
-mlr --ojson --jvquoteall cat test/input/json-output-options.dkvp
diff --git a/test/cases/io-json-io/0012/expout b/test/cases/io-json-io/0012/expout
deleted file mode 100644
index 331599995..000000000
--- a/test/cases/io-json-io/0012/expout
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "a": 1,
-  "b": "x",
-  "c": 3
-}
-{
-  "d": 4
-}
-{
-  "1": 5,
-  "f": 6
-}
diff --git a/test/cases/io-json-io/0013/cmd b/test/cases/io-json-io/0013/cmd
deleted file mode 100644
index db1af445a..000000000
--- a/test/cases/io-json-io/0013/cmd
+++ /dev/null
@@ -1 +0,0 @@
-mlr --ojson --jvstack --jvquoteall cat test/input/json-output-options.dkvp
diff --git a/test/cases/io-json-io/0013/expout b/test/cases/io-json-io/0013/expout
deleted file mode 100644
index 331599995..000000000
--- a/test/cases/io-json-io/0013/expout
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "a": 1,
-  "b": "x",
-  "c": 3
-}
-{
-  "d": 4
-}
-{
-  "1": 5,
-  "f": 6
-}
diff --git a/test/cases/io-json-io/0014/cmd b/test/cases/io-json-io/0014/cmd
deleted file mode 100644
index 231a14fa6..000000000
--- a/test/cases/io-json-io/0014/cmd
+++ /dev/null
@@ -1 +0,0 @@
-mlr --ojson --jlistwrap --jvquoteall cat test/input/json-output-options.dkvp
diff --git a/test/cases/io-json-io/0014/expout b/test/cases/io-json-io/0014/expout
deleted file mode 100644
index 0f3c7db9e..000000000
--- a/test/cases/io-json-io/0014/expout
+++ /dev/null
@@ -1,14 +0,0 @@
-[
-{
-  "a": 1,
-  "b": "x",
-  "c": 3
-},
-{
-  "d": 4
-},
-{
-  "1": 5,
-  "f": 6
-}
-]
diff --git a/test/cases/io-json-io/0015/cmd b/test/cases/io-json-io/0015/cmd
deleted file mode 100644
index e76fde4f0..000000000
--- a/test/cases/io-json-io/0015/cmd
+++ /dev/null
@@ -1 +0,0 @@
-mlr --ojson --jvstack --jlistwrap --jvquoteall cat test/input/json-output-options.dkvp
diff --git a/test/cases/io-json-io/0015/expout b/test/cases/io-json-io/0015/expout
deleted file mode 100644
index 0f3c7db9e..000000000
--- a/test/cases/io-json-io/0015/expout
+++ /dev/null
@@ -1,14 +0,0 @@
-[
-{
-  "a": 1,
-  "b": "x",
-  "c": 3
-},
-{
-  "d": 4
-},
-{
-  "1": 5,
-  "f": 6
-}
-]
diff --git a/test/cases/io-json-io/0016/cmd b/test/cases/io-json-io/0016/cmd
deleted file mode 100644
index e3bd48479..000000000
--- a/test/cases/io-json-io/0016/cmd
+++ /dev/null
@@ -1 +0,0 @@
-mlr --ojson --jknquoteint cat test/input/json-output-options.dkvp
diff --git a/test/cases/io-json-io/0016/expout b/test/cases/io-json-io/0016/expout
deleted file mode 100644
index 331599995..000000000
--- a/test/cases/io-json-io/0016/expout
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "a": 1,
-  "b": "x",
-  "c": 3
-}
-{
-  "d": 4
-}
-{
-  "1": 5,
-  "f": 6
-}
diff --git a/test/cases/io-json-io/0017/cmd b/test/cases/io-json-io/0017/cmd
deleted file mode 100644
index ac173fe34..000000000
--- a/test/cases/io-json-io/0017/cmd
+++ /dev/null
@@ -1 +0,0 @@
-mlr --ojson --jvstack --jknquoteint cat test/input/json-output-options.dkvp
diff --git a/test/cases/io-json-io/0017/expout b/test/cases/io-json-io/0017/expout
deleted file mode 100644
index 331599995..000000000
--- a/test/cases/io-json-io/0017/expout
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "a": 1,
-  "b": "x",
-  "c": 3
-}
-{
-  "d": 4
-}
-{
-  "1": 5,
-  "f": 6
-}
diff --git a/test/cases/io-json-io/0018/cmd b/test/cases/io-json-io/0018/cmd
deleted file mode 100644
index 4c2d8cabd..000000000
--- a/test/cases/io-json-io/0018/cmd
+++ /dev/null
@@ -1 +0,0 @@
-mlr --ojson --jlistwrap --jknquoteint cat test/input/json-output-options.dkvp
diff --git a/test/cases/io-json-io/0018/expout b/test/cases/io-json-io/0018/expout
deleted file mode 100644
index 0f3c7db9e..000000000
--- a/test/cases/io-json-io/0018/expout
+++ /dev/null
@@ -1,14 +0,0 @@
-[
-{
-  "a": 1,
-  "b": "x",
-  "c": 3
-},
-{
-  "d": 4
-},
-{
-  "1": 5,
-  "f": 6
-}
-]
diff --git a/test/cases/io-json-io/0019/cmd b/test/cases/io-json-io/0019/cmd
deleted file mode 100644
index dde570f78..000000000
--- a/test/cases/io-json-io/0019/cmd
+++ /dev/null
@@ -1 +0,0 @@
-mlr --ojson --jvstack --jlistwrap --jknquoteint cat test/input/json-output-options.dkvp
diff --git a/test/cases/io-json-io/0019/expout b/test/cases/io-json-io/0019/expout
deleted file mode 100644
index 0f3c7db9e..000000000
--- a/test/cases/io-json-io/0019/expout
+++ /dev/null
@@ -1,14 +0,0 @@
-[
-{
-  "a": 1,
-  "b": "x",
-  "c": 3
-},
-{
-  "d": 4
-},
-{
-  "1": 5,
-  "f": 6
-}
-]
diff --git a/test/cases/io-json-io/0020/cmd b/test/cases/io-json-io/0020/cmd
index f3e9821bf..ee1873b24 100644
--- a/test/cases/io-json-io/0020/cmd
+++ b/test/cases/io-json-io/0020/cmd
@@ -1 +1 @@
-mlr put -q --jvquoteall 'dump $*' test/input/json-output-options.dkvp
+mlr put -q 'dump $*' test/input/json-output-options.dkvp
diff --git a/test/cases/io-json-io/0021/cmd b/test/cases/io-json-io/0021/cmd
index d7d29a379..276c23696 100644
--- a/test/cases/io-json-io/0021/cmd
+++ b/test/cases/io-json-io/0021/cmd
@@ -1 +1 @@
-mlr put -q --jvquoteall 'o = $*; o[7] = 8; dump o' test/input/json-output-options.dkvp
+mlr put -q 'o = $*; o[7] = 8; dump o' test/input/json-output-options.dkvp
diff --git a/test/cases/io-json-io/0022/cmd b/test/cases/io-json-io/0022/cmd
deleted file mode 100644
index 40c423111..000000000
--- a/test/cases/io-json-io/0022/cmd
+++ /dev/null
@@ -1 +0,0 @@
-mlr put -q --jknquoteint 'dump $*' test/input/json-output-options.dkvp
diff --git a/test/cases/io-json-io/0022/expout b/test/cases/io-json-io/0022/expout
deleted file mode 100644
index 331599995..000000000
--- a/test/cases/io-json-io/0022/expout
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "a": 1,
-  "b": "x",
-  "c": 3
-}
-{
-  "d": 4
-}
-{
-  "1": 5,
-  "f": 6
-}
diff --git a/test/cases/io-json-io/0023/cmd b/test/cases/io-json-io/0023/cmd
deleted file mode 100644
index c4d448626..000000000
--- a/test/cases/io-json-io/0023/cmd
+++ /dev/null
@@ -1 +0,0 @@
-mlr put -q --jknquoteint 'o = $*; o[7] = 8; dump o' test/input/json-output-options.dkvp
diff --git a/test/cases/io-json-io/0025/expout b/test/cases/io-json-io/0025/expout
index 396b8be85..260b6dfb3 100644
--- a/test/cases/io-json-io/0025/expout
+++ b/test/cases/io-json-io/0025/expout
@@ -1,3 +1,5 @@
+[
 {
   "col": "abc \"def\" \\ghi"
 }
+]
diff --git a/test/cases/io-json-io/0026/cmd b/test/cases/io-json-io/0026/cmd
deleted file mode 100644
index 916a194ee..000000000
--- a/test/cases/io-json-io/0026/cmd
+++ /dev/null
@@ -1 +0,0 @@
-mlr --icsv --ojson --jvquoteall --rs lf cat ./${CASEDIR}/input
diff --git a/test/cases/io-json-io/0026/expout b/test/cases/io-json-io/0026/expout
deleted file mode 100644
index 396b8be85..000000000
--- a/test/cases/io-json-io/0026/expout
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "col": "abc \"def\" \\ghi"
-}
diff --git a/test/cases/io-json-io/0028/cmd b/test/cases/io-json-io/0028/cmd
deleted file mode 100644
index 4009752e8..000000000
--- a/test/cases/io-json-io/0028/cmd
+++ /dev/null
@@ -1 +0,0 @@
-mlr --ijson --oxtab --json-map-arrays-on-input cat test/input/arrays.json
diff --git a/test/cases/io-json-io/0028/experr b/test/cases/io-json-io/0028/experr
deleted file mode 100644
index e69de29bb..000000000
diff --git a/test/cases/io-json-io/0029/cmd b/test/cases/io-json-io/0029/cmd
deleted file mode 100644
index ec527c883..000000000
--- a/test/cases/io-json-io/0029/cmd
+++ /dev/null
@@ -1 +0,0 @@
-mlr --ijson --oxtab --json-skip-arrays-on-input cat test/input/arrays.json
diff --git a/test/cases/io-json-io/0029/experr b/test/cases/io-json-io/0029/experr
deleted file mode 100644
index e69de29bb..000000000
diff --git a/test/cases/io-json-io/0029/expout b/test/cases/io-json-io/0029/expout
deleted file mode 100644
index 6bd0dfbf8..000000000
--- a/test/cases/io-json-io/0029/expout
+++ /dev/null
@@ -1,23 +0,0 @@
-a 1
-b 1
-
-a   2
-b.1 2
-b.2 3
-
-a     3
-b.c.1 4
-b.c.2 5
-
-a       4
-b.c.d.1 4
-b.c.d.2 5
-
-a     5
-b.1   6
-b.2   7
-b.3.1 8
-b.3.2 9
-
-a       6
-b.1.1.1 11
diff --git a/test/cases/io-json-io/0030/cmd b/test/cases/io-json-io/0030/cmd
deleted file mode 100644
index a69c12c6a..000000000
--- a/test/cases/io-json-io/0030/cmd
+++ /dev/null
@@ -1 +0,0 @@
-mlr --ijson --oxtab --json-fatal-arrays-on-input cat test/input/arrays.json
diff --git a/test/cases/io-json-io/0030/experr b/test/cases/io-json-io/0030/experr
deleted file mode 100644
index e69de29bb..000000000
diff --git a/test/cases/io-json-io/0030/expout b/test/cases/io-json-io/0030/expout
deleted file mode 100644
index 6bd0dfbf8..000000000
--- a/test/cases/io-json-io/0030/expout
+++ /dev/null
@@ -1,23 +0,0 @@
-a 1
-b 1
-
-a   2
-b.1 2
-b.2 3
-
-a     3
-b.c.1 4
-b.c.2 5
-
-a       4
-b.c.d.1 4
-b.c.d.2 5
-
-a     5
-b.1   6
-b.2   7
-b.3.1 8
-b.3.2 9
-
-a       6
-b.1.1.1 11
diff --git a/test/cases/io-json-io/0031/expout b/test/cases/io-json-io/0031/expout
index ea81ff05b..ecce5f8c9 100644
--- a/test/cases/io-json-io/0031/expout
+++ b/test/cases/io-json-io/0031/expout
@@ -1,6 +1,8 @@
+[
 {
   "abc\bdef\fghi": "jkl\nmno\rpqr\tstu\"vw\\xyz"
-}
+},
 {
   "abc\bdef\fghi": "jkl\nmno\rpqr\tstu\"vw\\\\xyz"
 }
+]
diff --git a/test/cases/io-json-io/0032/expout b/test/cases/io-json-io/0032/expout
index 0e5f8f818..59fbd888e 100644
--- a/test/cases/io-json-io/0032/expout
+++ b/test/cases/io-json-io/0032/expout
@@ -1,6 +1,8 @@
+[
 {
   "m": "a\"b\"c"
-}
+},
 {
   "m": "a\\\"b\\\"c"
 }
+]
diff --git a/test/cases/io-json-io/0033/expout b/test/cases/io-json-io/0033/expout
index d4f155daf..ed63a78b9 100644
--- a/test/cases/io-json-io/0033/expout
+++ b/test/cases/io-json-io/0033/expout
@@ -1,6 +1,8 @@
+[
 {
   "x": 1,
   "n": null,
   "y": 3,
   "z": 4
 }
+]
diff --git a/test/cases/io-json-io/0034/expout b/test/cases/io-json-io/0034/expout
index 2edda76f4..66c99aa72 100644
--- a/test/cases/io-json-io/0034/expout
+++ b/test/cases/io-json-io/0034/expout
@@ -1,6 +1,8 @@
+[
 {
   "x": 1,
   "n": null,
   "y": 3,
   "z": 3
 }
+]
diff --git a/test/cases/io-json-io/0035/expout b/test/cases/io-json-io/0035/expout
index 6073b24f6..060ade778 100644
--- a/test/cases/io-json-io/0035/expout
+++ b/test/cases/io-json-io/0035/expout
@@ -1,6 +1,8 @@
+[
 {
   "x": 1,
   "n": null,
   "y": 3,
   "z": null
 }
+]
diff --git a/test/cases/io-jsonl-io/0001/cmd b/test/cases/io-jsonl-io/0001/cmd
new file mode 100644
index 000000000..1b8b6ef94
--- /dev/null
+++ b/test/cases/io-jsonl-io/0001/cmd
@@ -0,0 +1 @@
+mlr --ijsonl --opprint cat test/input/small-non-nested.json
diff --git a/test/cases/io-json-io/0006/experr b/test/cases/io-jsonl-io/0001/experr
similarity index 100%
rename from test/cases/io-json-io/0006/experr
rename to test/cases/io-jsonl-io/0001/experr
diff --git a/test/cases/io-jsonl-io/0001/expout b/test/cases/io-jsonl-io/0001/expout
new file mode 100644
index 000000000..c894dcf82
--- /dev/null
+++ b/test/cases/io-jsonl-io/0001/expout
@@ -0,0 +1,11 @@
+a   b   i  x                   y
+pan pan 1  0.3467901443380824  0.7268028627434533
+eks pan 2  0.7586799647899636  0.5221511083334797
+wye wye 3  0.20460330576630303 0.33831852551664776
+eks wye 4  0.38139939387114097 0.13418874328430463
+wye pan 5  0.5732889198020006  0.8636244699032729
+zee pan 6  0.5271261600918548  0.49322128674835697
+eks zee 7  0.6117840605678454  0.1878849191181694
+zee wye 8  0.5985540091064224  0.976181385699006
+hat wye 9  0.03144187646093577 0.7495507603507059
+pan wye 10 0.5026260055412137  0.9526183602969864
diff --git a/test/cases/io-jsonl-io/0002/cmd b/test/cases/io-jsonl-io/0002/cmd
new file mode 100644
index 000000000..5e8133e01
--- /dev/null
+++ b/test/cases/io-jsonl-io/0002/cmd
@@ -0,0 +1 @@
+mlr --ijsonl --opprint cat test/input/small-non-nested-wrapped.json
diff --git a/test/cases/io-json-io/0007/experr b/test/cases/io-jsonl-io/0002/experr
similarity index 100%
rename from test/cases/io-json-io/0007/experr
rename to test/cases/io-jsonl-io/0002/experr
diff --git a/test/cases/io-jsonl-io/0002/expout b/test/cases/io-jsonl-io/0002/expout
new file mode 100644
index 000000000..c894dcf82
--- /dev/null
+++ b/test/cases/io-jsonl-io/0002/expout
@@ -0,0 +1,11 @@
+a   b   i  x                   y
+pan pan 1  0.3467901443380824  0.7268028627434533
+eks pan 2  0.7586799647899636  0.5221511083334797
+wye wye 3  0.20460330576630303 0.33831852551664776
+eks wye 4  0.38139939387114097 0.13418874328430463
+wye pan 5  0.5732889198020006  0.8636244699032729
+zee pan 6  0.5271261600918548  0.49322128674835697
+eks zee 7  0.6117840605678454  0.1878849191181694
+zee wye 8  0.5985540091064224  0.976181385699006
+hat wye 9  0.03144187646093577 0.7495507603507059
+pan wye 10 0.5026260055412137  0.9526183602969864
diff --git a/test/cases/io-jsonl-io/0003/cmd b/test/cases/io-jsonl-io/0003/cmd
new file mode 100644
index 000000000..5f5e44349
--- /dev/null
+++ b/test/cases/io-jsonl-io/0003/cmd
@@ -0,0 +1 @@
+mlr --ijsonl --oxtab cat test/input/small-nested.json
diff --git a/test/cases/io-json-io/0008/experr b/test/cases/io-jsonl-io/0003/experr
similarity index 100%
rename from test/cases/io-json-io/0008/experr
rename to test/cases/io-jsonl-io/0003/experr
diff --git a/test/cases/io-jsonl-io/0003/expout b/test/cases/io-jsonl-io/0003/expout
new file mode 100644
index 000000000..72a888ca1
--- /dev/null
+++ b/test/cases/io-jsonl-io/0003/expout
@@ -0,0 +1,7 @@
+z.pan.1 0.726803
+z.pan.0 0.952618
+z.eks.0 0.134189
+z.eks.1 0.187885
+z.wye.1 0.863624
+z.zee.0 0.976181
+z.hat.1 0.749551
diff --git a/test/cases/io-jsonl-io/0004/cmd b/test/cases/io-jsonl-io/0004/cmd
new file mode 100644
index 000000000..380bba0ca
--- /dev/null
+++ b/test/cases/io-jsonl-io/0004/cmd
@@ -0,0 +1 @@
+mlr --ojsonl cat test/input/json-output-options.dkvp
diff --git a/test/cases/io-json-io/0009/experr b/test/cases/io-jsonl-io/0004/experr
similarity index 100%
rename from test/cases/io-json-io/0009/experr
rename to test/cases/io-jsonl-io/0004/experr
diff --git a/test/cases/io-jsonl-io/0004/expout b/test/cases/io-jsonl-io/0004/expout
new file mode 100644
index 000000000..ebae2f745
--- /dev/null
+++ b/test/cases/io-jsonl-io/0004/expout
@@ -0,0 +1,3 @@
+{"a": 1, "b": "x", "c": 3}
+{"d": 4}
+{"1": 5, "f": 6}
diff --git a/test/cases/io-jsonl-io/0005/cmd b/test/cases/io-jsonl-io/0005/cmd
new file mode 100644
index 000000000..e29040c90
--- /dev/null
+++ b/test/cases/io-jsonl-io/0005/cmd
@@ -0,0 +1 @@
+mlr --ojsonl --no-jvstack cat test/input/json-output-options.dkvp
diff --git a/test/cases/io-json-io/0010/experr b/test/cases/io-jsonl-io/0005/experr
similarity index 100%
rename from test/cases/io-json-io/0010/experr
rename to test/cases/io-jsonl-io/0005/experr
diff --git a/test/cases/io-jsonl-io/0005/expout b/test/cases/io-jsonl-io/0005/expout
new file mode 100644
index 000000000..ebae2f745
--- /dev/null
+++ b/test/cases/io-jsonl-io/0005/expout
@@ -0,0 +1,3 @@
+{"a": 1, "b": "x", "c": 3}
+{"d": 4}
+{"1": 5, "f": 6}
diff --git a/test/cases/io-jsonl-io/0011/cmd b/test/cases/io-jsonl-io/0011/cmd
new file mode 100644
index 000000000..eec728792
--- /dev/null
+++ b/test/cases/io-jsonl-io/0011/cmd
@@ -0,0 +1 @@
+mlr --ojsonl --jquoteall cat test/input/json-output-options.dkvp
diff --git a/test/cases/io-json-io/0012/experr b/test/cases/io-jsonl-io/0011/experr
similarity index 100%
rename from test/cases/io-json-io/0012/experr
rename to test/cases/io-jsonl-io/0011/experr
diff --git a/test/cases/io-jsonl-io/0011/expout b/test/cases/io-jsonl-io/0011/expout
new file mode 100644
index 000000000..ebae2f745
--- /dev/null
+++ b/test/cases/io-jsonl-io/0011/expout
@@ -0,0 +1,3 @@
+{"a": 1, "b": "x", "c": 3}
+{"d": 4}
+{"1": 5, "f": 6}
diff --git a/test/cases/io-jsonl-io/0020/cmd b/test/cases/io-jsonl-io/0020/cmd
new file mode 100644
index 000000000..ee1873b24
--- /dev/null
+++ b/test/cases/io-jsonl-io/0020/cmd
@@ -0,0 +1 @@
+mlr put -q 'dump $*' test/input/json-output-options.dkvp
diff --git a/test/cases/io-json-io/0013/experr b/test/cases/io-jsonl-io/0020/experr
similarity index 100%
rename from test/cases/io-json-io/0013/experr
rename to test/cases/io-jsonl-io/0020/experr
diff --git a/test/cases/io-json-io/0008/expout b/test/cases/io-jsonl-io/0020/expout
similarity index 100%
rename from test/cases/io-json-io/0008/expout
rename to test/cases/io-jsonl-io/0020/expout
diff --git a/test/cases/io-jsonl-io/0021/cmd b/test/cases/io-jsonl-io/0021/cmd
new file mode 100644
index 000000000..276c23696
--- /dev/null
+++ b/test/cases/io-jsonl-io/0021/cmd
@@ -0,0 +1 @@
+mlr put -q 'o = $*; o[7] = 8; dump o' test/input/json-output-options.dkvp
diff --git a/test/cases/io-json-io/0014/experr b/test/cases/io-jsonl-io/0021/experr
similarity index 100%
rename from test/cases/io-json-io/0014/experr
rename to test/cases/io-jsonl-io/0021/experr
diff --git a/test/cases/io-json-io/0023/expout b/test/cases/io-jsonl-io/0021/expout
similarity index 100%
rename from test/cases/io-json-io/0023/expout
rename to test/cases/io-jsonl-io/0021/expout
diff --git a/test/cases/io-jsonl-io/0024/cmd b/test/cases/io-jsonl-io/0024/cmd
new file mode 100644
index 000000000..8c11118f1
--- /dev/null
+++ b/test/cases/io-jsonl-io/0024/cmd
@@ -0,0 +1 @@
+mlr --ijsonl --opprint cat test/input/small-non-nested-wrapped.json test/input/small-non-nested-wrapped.json
diff --git a/test/cases/io-json-io/0015/experr b/test/cases/io-jsonl-io/0024/experr
similarity index 100%
rename from test/cases/io-json-io/0015/experr
rename to test/cases/io-jsonl-io/0024/experr
diff --git a/test/cases/io-jsonl-io/0024/expout b/test/cases/io-jsonl-io/0024/expout
new file mode 100644
index 000000000..7b1f8fc05
--- /dev/null
+++ b/test/cases/io-jsonl-io/0024/expout
@@ -0,0 +1,21 @@
+a   b   i  x                   y
+pan pan 1  0.3467901443380824  0.7268028627434533
+eks pan 2  0.7586799647899636  0.5221511083334797
+wye wye 3  0.20460330576630303 0.33831852551664776
+eks wye 4  0.38139939387114097 0.13418874328430463
+wye pan 5  0.5732889198020006  0.8636244699032729
+zee pan 6  0.5271261600918548  0.49322128674835697
+eks zee 7  0.6117840605678454  0.1878849191181694
+zee wye 8  0.5985540091064224  0.976181385699006
+hat wye 9  0.03144187646093577 0.7495507603507059
+pan wye 10 0.5026260055412137  0.9526183602969864
+pan pan 1  0.3467901443380824  0.7268028627434533
+eks pan 2  0.7586799647899636  0.5221511083334797
+wye wye 3  0.20460330576630303 0.33831852551664776
+eks wye 4  0.38139939387114097 0.13418874328430463
+wye pan 5  0.5732889198020006  0.8636244699032729
+zee pan 6  0.5271261600918548  0.49322128674835697
+eks zee 7  0.6117840605678454  0.1878849191181694
+zee wye 8  0.5985540091064224  0.976181385699006
+hat wye 9  0.03144187646093577 0.7495507603507059
+pan wye 10 0.5026260055412137  0.9526183602969864
diff --git a/test/cases/io-jsonl-io/0025/cmd b/test/cases/io-jsonl-io/0025/cmd
new file mode 100644
index 000000000..6f71287ee
--- /dev/null
+++ b/test/cases/io-jsonl-io/0025/cmd
@@ -0,0 +1 @@
+mlr --icsv --ojsonl --rs lf cat ./${CASEDIR}/input
diff --git a/test/cases/io-json-io/0016/experr b/test/cases/io-jsonl-io/0025/experr
similarity index 100%
rename from test/cases/io-json-io/0016/experr
rename to test/cases/io-jsonl-io/0025/experr
diff --git a/test/cases/io-jsonl-io/0025/expout b/test/cases/io-jsonl-io/0025/expout
new file mode 100644
index 000000000..632fb7bb6
--- /dev/null
+++ b/test/cases/io-jsonl-io/0025/expout
@@ -0,0 +1 @@
+{"col": "abc \"def\" \\ghi"}
diff --git a/test/cases/io-json-io/0026/input b/test/cases/io-jsonl-io/0025/input
similarity index 100%
rename from test/cases/io-json-io/0026/input
rename to test/cases/io-jsonl-io/0025/input
diff --git a/test/cases/io-jsonl-io/0027/cmd b/test/cases/io-jsonl-io/0027/cmd
new file mode 100644
index 000000000..02df6742a
--- /dev/null
+++ b/test/cases/io-jsonl-io/0027/cmd
@@ -0,0 +1 @@
+mlr --ijsonl --oxtab cat test/input/arrays.json
diff --git a/test/cases/io-json-io/0017/experr b/test/cases/io-jsonl-io/0027/experr
similarity index 100%
rename from test/cases/io-json-io/0017/experr
rename to test/cases/io-jsonl-io/0027/experr
diff --git a/test/cases/io-json-io/0028/expout b/test/cases/io-jsonl-io/0027/expout
similarity index 100%
rename from test/cases/io-json-io/0028/expout
rename to test/cases/io-jsonl-io/0027/expout
diff --git a/test/cases/io-jsonl-io/0031/cmd b/test/cases/io-jsonl-io/0031/cmd
new file mode 100644
index 000000000..427d5ae2d
--- /dev/null
+++ b/test/cases/io-jsonl-io/0031/cmd
@@ -0,0 +1 @@
+mlr --jsonl cat test/input/escapes.json
diff --git a/test/cases/io-json-io/0018/experr b/test/cases/io-jsonl-io/0031/experr
similarity index 100%
rename from test/cases/io-json-io/0018/experr
rename to test/cases/io-jsonl-io/0031/experr
diff --git a/test/cases/io-jsonl-io/0031/expout b/test/cases/io-jsonl-io/0031/expout
new file mode 100644
index 000000000..144f10ea8
--- /dev/null
+++ b/test/cases/io-jsonl-io/0031/expout
@@ -0,0 +1,2 @@
+{"abcdefghi": "jkl\nmno\rpqr\tstu\"vw\\xyz"}
+{"abcdefghi": "jkl\nmno\rpqr\tstu\"vw\\\\xyz"}
diff --git a/test/cases/io-jsonl-io/0032/cmd b/test/cases/io-jsonl-io/0032/cmd
new file mode 100644
index 000000000..e52fb441d
--- /dev/null
+++ b/test/cases/io-jsonl-io/0032/cmd
@@ -0,0 +1 @@
+mlr --jsonl cat test/input/backslashes.json
diff --git a/test/cases/io-json-io/0019/experr b/test/cases/io-jsonl-io/0032/experr
similarity index 100%
rename from test/cases/io-json-io/0019/experr
rename to test/cases/io-jsonl-io/0032/experr
diff --git a/test/cases/io-jsonl-io/0032/expout b/test/cases/io-jsonl-io/0032/expout
new file mode 100644
index 000000000..8b05ade35
--- /dev/null
+++ b/test/cases/io-jsonl-io/0032/expout
@@ -0,0 +1,2 @@
+{"m": "a\"b\"c"}
+{"m": "a\\\"b\\\"c"}
diff --git a/test/cases/io-jsonl-io/0033/cmd b/test/cases/io-jsonl-io/0033/cmd
new file mode 100644
index 000000000..d4136b39c
--- /dev/null
+++ b/test/cases/io-jsonl-io/0033/cmd
@@ -0,0 +1 @@
+mlr --jsonl --from test/input/nulls.json put '$z=$x+$y'
diff --git a/test/cases/io-json-io/0022/experr b/test/cases/io-jsonl-io/0033/experr
similarity index 100%
rename from test/cases/io-json-io/0022/experr
rename to test/cases/io-jsonl-io/0033/experr
diff --git a/test/cases/io-jsonl-io/0033/expout b/test/cases/io-jsonl-io/0033/expout
new file mode 100644
index 000000000..95ccb6fb1
--- /dev/null
+++ b/test/cases/io-jsonl-io/0033/expout
@@ -0,0 +1 @@
+{"x": 1, "n": null, "y": 3, "z": 4}
diff --git a/test/cases/io-jsonl-io/0034/cmd b/test/cases/io-jsonl-io/0034/cmd
new file mode 100644
index 000000000..ad432d791
--- /dev/null
+++ b/test/cases/io-jsonl-io/0034/cmd
@@ -0,0 +1 @@
+mlr --jsonl --from test/input/nulls.json put '$z=$n+$y'
diff --git a/test/cases/io-json-io/0023/experr b/test/cases/io-jsonl-io/0034/experr
similarity index 100%
rename from test/cases/io-json-io/0023/experr
rename to test/cases/io-jsonl-io/0034/experr
diff --git a/test/cases/io-jsonl-io/0034/expout b/test/cases/io-jsonl-io/0034/expout
new file mode 100644
index 000000000..65a36898f
--- /dev/null
+++ b/test/cases/io-jsonl-io/0034/expout
@@ -0,0 +1 @@
+{"x": 1, "n": null, "y": 3, "z": 3}
diff --git a/test/cases/io-jsonl-io/0035/cmd b/test/cases/io-jsonl-io/0035/cmd
new file mode 100644
index 000000000..121df3da4
--- /dev/null
+++ b/test/cases/io-jsonl-io/0035/cmd
@@ -0,0 +1 @@
+mlr --jsonl --from test/input/nulls.json put '$z=$n+$n'
diff --git a/test/cases/io-json-io/0026/experr b/test/cases/io-jsonl-io/0035/experr
similarity index 100%
rename from test/cases/io-json-io/0026/experr
rename to test/cases/io-jsonl-io/0035/experr
diff --git a/test/cases/io-jsonl-io/0035/expout b/test/cases/io-jsonl-io/0035/expout
new file mode 100644
index 000000000..4148c533e
--- /dev/null
+++ b/test/cases/io-jsonl-io/0035/expout
@@ -0,0 +1 @@
+{"x": 1, "n": null, "y": 3, "z": null}
diff --git a/test/cases/io-lf-crlf-and-autodetect/0029/expout b/test/cases/io-lf-crlf-and-autodetect/0029/expout
index 686f30737..a619474e4 100644
--- a/test/cases/io-lf-crlf-and-autodetect/0029/expout
+++ b/test/cases/io-lf-crlf-and-autodetect/0029/expout
@@ -1,66 +1,67 @@
+[
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": "eks",
   "b": "pan",
   "i": 2,
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
-}
+},
 {
   "a": "wye",
   "b": "wye",
   "i": 3,
   "x": 0.20460330576630303,
   "y": 0.33831852551664776
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "i": 4,
   "x": 0.38139939387114097,
   "y": 0.13418874328430463
-}
+},
 {
   "a": "wye",
   "b": "pan",
   "i": 5,
   "x": 0.5732889198020006,
   "y": 0.8636244699032729
-}
+},
 {
   "a": "zee",
   "b": "pan",
   "i": 6,
   "x": 0.5271261600918548,
   "y": 0.49322128674835697
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "i": 7,
   "x": 0.6117840605678454,
   "y": 0.1878849191181694
-}
+},
 {
   "a": "zee",
   "b": "wye",
   "i": 8,
   "x": 0.5985540091064224,
   "y": 0.976181385699006
-}
+},
 {
   "a": "hat",
   "b": "wye",
   "i": 9,
   "x": 0.03144187646093577,
   "y": 0.7495507603507059
-}
+},
 {
   "a": "pan",
   "b": "wye",
@@ -68,3 +69,4 @@
   "x": 0.5026260055412137,
   "y": 0.9526183602969864
 }
+]
diff --git a/test/cases/io-lf-crlf-and-autodetect/0030/expout b/test/cases/io-lf-crlf-and-autodetect/0030/expout
index 686f30737..a619474e4 100644
--- a/test/cases/io-lf-crlf-and-autodetect/0030/expout
+++ b/test/cases/io-lf-crlf-and-autodetect/0030/expout
@@ -1,66 +1,67 @@
+[
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": "eks",
   "b": "pan",
   "i": 2,
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
-}
+},
 {
   "a": "wye",
   "b": "wye",
   "i": 3,
   "x": 0.20460330576630303,
   "y": 0.33831852551664776
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "i": 4,
   "x": 0.38139939387114097,
   "y": 0.13418874328430463
-}
+},
 {
   "a": "wye",
   "b": "pan",
   "i": 5,
   "x": 0.5732889198020006,
   "y": 0.8636244699032729
-}
+},
 {
   "a": "zee",
   "b": "pan",
   "i": 6,
   "x": 0.5271261600918548,
   "y": 0.49322128674835697
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "i": 7,
   "x": 0.6117840605678454,
   "y": 0.1878849191181694
-}
+},
 {
   "a": "zee",
   "b": "wye",
   "i": 8,
   "x": 0.5985540091064224,
   "y": 0.976181385699006
-}
+},
 {
   "a": "hat",
   "b": "wye",
   "i": 9,
   "x": 0.03144187646093577,
   "y": 0.7495507603507059
-}
+},
 {
   "a": "pan",
   "b": "wye",
@@ -68,3 +69,4 @@
   "x": 0.5026260055412137,
   "y": 0.9526183602969864
 }
+]
diff --git a/test/cases/io-lf-crlf-and-autodetect/0031/expout b/test/cases/io-lf-crlf-and-autodetect/0031/expout
index 686f30737..a619474e4 100644
--- a/test/cases/io-lf-crlf-and-autodetect/0031/expout
+++ b/test/cases/io-lf-crlf-and-autodetect/0031/expout
@@ -1,66 +1,67 @@
+[
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": "eks",
   "b": "pan",
   "i": 2,
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
-}
+},
 {
   "a": "wye",
   "b": "wye",
   "i": 3,
   "x": 0.20460330576630303,
   "y": 0.33831852551664776
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "i": 4,
   "x": 0.38139939387114097,
   "y": 0.13418874328430463
-}
+},
 {
   "a": "wye",
   "b": "pan",
   "i": 5,
   "x": 0.5732889198020006,
   "y": 0.8636244699032729
-}
+},
 {
   "a": "zee",
   "b": "pan",
   "i": 6,
   "x": 0.5271261600918548,
   "y": 0.49322128674835697
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "i": 7,
   "x": 0.6117840605678454,
   "y": 0.1878849191181694
-}
+},
 {
   "a": "zee",
   "b": "wye",
   "i": 8,
   "x": 0.5985540091064224,
   "y": 0.976181385699006
-}
+},
 {
   "a": "hat",
   "b": "wye",
   "i": 9,
   "x": 0.03144187646093577,
   "y": 0.7495507603507059
-}
+},
 {
   "a": "pan",
   "b": "wye",
@@ -68,3 +69,4 @@
   "x": 0.5026260055412137,
   "y": 0.9526183602969864
 }
+]
diff --git a/test/cases/io-lf-crlf-and-autodetect/0032/expout b/test/cases/io-lf-crlf-and-autodetect/0032/expout
index 686f30737..a619474e4 100644
--- a/test/cases/io-lf-crlf-and-autodetect/0032/expout
+++ b/test/cases/io-lf-crlf-and-autodetect/0032/expout
@@ -1,66 +1,67 @@
+[
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": "eks",
   "b": "pan",
   "i": 2,
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
-}
+},
 {
   "a": "wye",
   "b": "wye",
   "i": 3,
   "x": 0.20460330576630303,
   "y": 0.33831852551664776
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "i": 4,
   "x": 0.38139939387114097,
   "y": 0.13418874328430463
-}
+},
 {
   "a": "wye",
   "b": "pan",
   "i": 5,
   "x": 0.5732889198020006,
   "y": 0.8636244699032729
-}
+},
 {
   "a": "zee",
   "b": "pan",
   "i": 6,
   "x": 0.5271261600918548,
   "y": 0.49322128674835697
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "i": 7,
   "x": 0.6117840605678454,
   "y": 0.1878849191181694
-}
+},
 {
   "a": "zee",
   "b": "wye",
   "i": 8,
   "x": 0.5985540091064224,
   "y": 0.976181385699006
-}
+},
 {
   "a": "hat",
   "b": "wye",
   "i": 9,
   "x": 0.03144187646093577,
   "y": 0.7495507603507059
-}
+},
 {
   "a": "pan",
   "b": "wye",
@@ -68,3 +69,4 @@
   "x": 0.5026260055412137,
   "y": 0.9526183602969864
 }
+]
diff --git a/test/cases/io-lf-crlf-and-autodetect/0037/expout b/test/cases/io-lf-crlf-and-autodetect/0037/expout
index 686f30737..a619474e4 100644
--- a/test/cases/io-lf-crlf-and-autodetect/0037/expout
+++ b/test/cases/io-lf-crlf-and-autodetect/0037/expout
@@ -1,66 +1,67 @@
+[
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": "eks",
   "b": "pan",
   "i": 2,
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
-}
+},
 {
   "a": "wye",
   "b": "wye",
   "i": 3,
   "x": 0.20460330576630303,
   "y": 0.33831852551664776
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "i": 4,
   "x": 0.38139939387114097,
   "y": 0.13418874328430463
-}
+},
 {
   "a": "wye",
   "b": "pan",
   "i": 5,
   "x": 0.5732889198020006,
   "y": 0.8636244699032729
-}
+},
 {
   "a": "zee",
   "b": "pan",
   "i": 6,
   "x": 0.5271261600918548,
   "y": 0.49322128674835697
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "i": 7,
   "x": 0.6117840605678454,
   "y": 0.1878849191181694
-}
+},
 {
   "a": "zee",
   "b": "wye",
   "i": 8,
   "x": 0.5985540091064224,
   "y": 0.976181385699006
-}
+},
 {
   "a": "hat",
   "b": "wye",
   "i": 9,
   "x": 0.03144187646093577,
   "y": 0.7495507603507059
-}
+},
 {
   "a": "pan",
   "b": "wye",
@@ -68,3 +69,4 @@
   "x": 0.5026260055412137,
   "y": 0.9526183602969864
 }
+]
diff --git a/test/cases/io-lf-crlf-and-autodetect/0038/expout b/test/cases/io-lf-crlf-and-autodetect/0038/expout
index 686f30737..a619474e4 100644
--- a/test/cases/io-lf-crlf-and-autodetect/0038/expout
+++ b/test/cases/io-lf-crlf-and-autodetect/0038/expout
@@ -1,66 +1,67 @@
+[
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": "eks",
   "b": "pan",
   "i": 2,
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
-}
+},
 {
   "a": "wye",
   "b": "wye",
   "i": 3,
   "x": 0.20460330576630303,
   "y": 0.33831852551664776
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "i": 4,
   "x": 0.38139939387114097,
   "y": 0.13418874328430463
-}
+},
 {
   "a": "wye",
   "b": "pan",
   "i": 5,
   "x": 0.5732889198020006,
   "y": 0.8636244699032729
-}
+},
 {
   "a": "zee",
   "b": "pan",
   "i": 6,
   "x": 0.5271261600918548,
   "y": 0.49322128674835697
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "i": 7,
   "x": 0.6117840605678454,
   "y": 0.1878849191181694
-}
+},
 {
   "a": "zee",
   "b": "wye",
   "i": 8,
   "x": 0.5985540091064224,
   "y": 0.976181385699006
-}
+},
 {
   "a": "hat",
   "b": "wye",
   "i": 9,
   "x": 0.03144187646093577,
   "y": 0.7495507603507059
-}
+},
 {
   "a": "pan",
   "b": "wye",
@@ -68,3 +69,4 @@
   "x": 0.5026260055412137,
   "y": 0.9526183602969864
 }
+]
diff --git a/test/cases/io-lf-crlf-and-autodetect/0039/expout b/test/cases/io-lf-crlf-and-autodetect/0039/expout
index 686f30737..a619474e4 100644
--- a/test/cases/io-lf-crlf-and-autodetect/0039/expout
+++ b/test/cases/io-lf-crlf-and-autodetect/0039/expout
@@ -1,66 +1,67 @@
+[
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": "eks",
   "b": "pan",
   "i": 2,
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
-}
+},
 {
   "a": "wye",
   "b": "wye",
   "i": 3,
   "x": 0.20460330576630303,
   "y": 0.33831852551664776
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "i": 4,
   "x": 0.38139939387114097,
   "y": 0.13418874328430463
-}
+},
 {
   "a": "wye",
   "b": "pan",
   "i": 5,
   "x": 0.5732889198020006,
   "y": 0.8636244699032729
-}
+},
 {
   "a": "zee",
   "b": "pan",
   "i": 6,
   "x": 0.5271261600918548,
   "y": 0.49322128674835697
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "i": 7,
   "x": 0.6117840605678454,
   "y": 0.1878849191181694
-}
+},
 {
   "a": "zee",
   "b": "wye",
   "i": 8,
   "x": 0.5985540091064224,
   "y": 0.976181385699006
-}
+},
 {
   "a": "hat",
   "b": "wye",
   "i": 9,
   "x": 0.03144187646093577,
   "y": 0.7495507603507059
-}
+},
 {
   "a": "pan",
   "b": "wye",
@@ -68,3 +69,4 @@
   "x": 0.5026260055412137,
   "y": 0.9526183602969864
 }
+]
diff --git a/test/cases/io-lf-crlf-and-autodetect/0040/expout b/test/cases/io-lf-crlf-and-autodetect/0040/expout
index 686f30737..a619474e4 100644
--- a/test/cases/io-lf-crlf-and-autodetect/0040/expout
+++ b/test/cases/io-lf-crlf-and-autodetect/0040/expout
@@ -1,66 +1,67 @@
+[
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": "eks",
   "b": "pan",
   "i": 2,
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
-}
+},
 {
   "a": "wye",
   "b": "wye",
   "i": 3,
   "x": 0.20460330576630303,
   "y": 0.33831852551664776
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "i": 4,
   "x": 0.38139939387114097,
   "y": 0.13418874328430463
-}
+},
 {
   "a": "wye",
   "b": "pan",
   "i": 5,
   "x": 0.5732889198020006,
   "y": 0.8636244699032729
-}
+},
 {
   "a": "zee",
   "b": "pan",
   "i": 6,
   "x": 0.5271261600918548,
   "y": 0.49322128674835697
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "i": 7,
   "x": 0.6117840605678454,
   "y": 0.1878849191181694
-}
+},
 {
   "a": "zee",
   "b": "wye",
   "i": 8,
   "x": 0.5985540091064224,
   "y": 0.976181385699006
-}
+},
 {
   "a": "hat",
   "b": "wye",
   "i": 9,
   "x": 0.03144187646093577,
   "y": 0.7495507603507059
-}
+},
 {
   "a": "pan",
   "b": "wye",
@@ -68,3 +69,4 @@
   "x": 0.5026260055412137,
   "y": 0.9526183602969864
 }
+]
diff --git a/test/cases/io-lf-crlf-and-autodetect/0045/expout b/test/cases/io-lf-crlf-and-autodetect/0045/expout
index 686f30737..a619474e4 100644
--- a/test/cases/io-lf-crlf-and-autodetect/0045/expout
+++ b/test/cases/io-lf-crlf-and-autodetect/0045/expout
@@ -1,66 +1,67 @@
+[
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": "eks",
   "b": "pan",
   "i": 2,
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
-}
+},
 {
   "a": "wye",
   "b": "wye",
   "i": 3,
   "x": 0.20460330576630303,
   "y": 0.33831852551664776
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "i": 4,
   "x": 0.38139939387114097,
   "y": 0.13418874328430463
-}
+},
 {
   "a": "wye",
   "b": "pan",
   "i": 5,
   "x": 0.5732889198020006,
   "y": 0.8636244699032729
-}
+},
 {
   "a": "zee",
   "b": "pan",
   "i": 6,
   "x": 0.5271261600918548,
   "y": 0.49322128674835697
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "i": 7,
   "x": 0.6117840605678454,
   "y": 0.1878849191181694
-}
+},
 {
   "a": "zee",
   "b": "wye",
   "i": 8,
   "x": 0.5985540091064224,
   "y": 0.976181385699006
-}
+},
 {
   "a": "hat",
   "b": "wye",
   "i": 9,
   "x": 0.03144187646093577,
   "y": 0.7495507603507059
-}
+},
 {
   "a": "pan",
   "b": "wye",
@@ -68,3 +69,4 @@
   "x": 0.5026260055412137,
   "y": 0.9526183602969864
 }
+]
diff --git a/test/cases/io-lf-crlf-and-autodetect/0046/expout b/test/cases/io-lf-crlf-and-autodetect/0046/expout
index 686f30737..a619474e4 100644
--- a/test/cases/io-lf-crlf-and-autodetect/0046/expout
+++ b/test/cases/io-lf-crlf-and-autodetect/0046/expout
@@ -1,66 +1,67 @@
+[
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": "eks",
   "b": "pan",
   "i": 2,
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
-}
+},
 {
   "a": "wye",
   "b": "wye",
   "i": 3,
   "x": 0.20460330576630303,
   "y": 0.33831852551664776
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "i": 4,
   "x": 0.38139939387114097,
   "y": 0.13418874328430463
-}
+},
 {
   "a": "wye",
   "b": "pan",
   "i": 5,
   "x": 0.5732889198020006,
   "y": 0.8636244699032729
-}
+},
 {
   "a": "zee",
   "b": "pan",
   "i": 6,
   "x": 0.5271261600918548,
   "y": 0.49322128674835697
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "i": 7,
   "x": 0.6117840605678454,
   "y": 0.1878849191181694
-}
+},
 {
   "a": "zee",
   "b": "wye",
   "i": 8,
   "x": 0.5985540091064224,
   "y": 0.976181385699006
-}
+},
 {
   "a": "hat",
   "b": "wye",
   "i": 9,
   "x": 0.03144187646093577,
   "y": 0.7495507603507059
-}
+},
 {
   "a": "pan",
   "b": "wye",
@@ -68,3 +69,4 @@
   "x": 0.5026260055412137,
   "y": 0.9526183602969864
 }
+]
diff --git a/test/cases/io-lf-crlf-and-autodetect/0047/expout b/test/cases/io-lf-crlf-and-autodetect/0047/expout
index 686f30737..a619474e4 100644
--- a/test/cases/io-lf-crlf-and-autodetect/0047/expout
+++ b/test/cases/io-lf-crlf-and-autodetect/0047/expout
@@ -1,66 +1,67 @@
+[
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": "eks",
   "b": "pan",
   "i": 2,
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
-}
+},
 {
   "a": "wye",
   "b": "wye",
   "i": 3,
   "x": 0.20460330576630303,
   "y": 0.33831852551664776
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "i": 4,
   "x": 0.38139939387114097,
   "y": 0.13418874328430463
-}
+},
 {
   "a": "wye",
   "b": "pan",
   "i": 5,
   "x": 0.5732889198020006,
   "y": 0.8636244699032729
-}
+},
 {
   "a": "zee",
   "b": "pan",
   "i": 6,
   "x": 0.5271261600918548,
   "y": 0.49322128674835697
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "i": 7,
   "x": 0.6117840605678454,
   "y": 0.1878849191181694
-}
+},
 {
   "a": "zee",
   "b": "wye",
   "i": 8,
   "x": 0.5985540091064224,
   "y": 0.976181385699006
-}
+},
 {
   "a": "hat",
   "b": "wye",
   "i": 9,
   "x": 0.03144187646093577,
   "y": 0.7495507603507059
-}
+},
 {
   "a": "pan",
   "b": "wye",
@@ -68,3 +69,4 @@
   "x": 0.5026260055412137,
   "y": 0.9526183602969864
 }
+]
diff --git a/test/cases/io-lf-crlf-and-autodetect/0048/expout b/test/cases/io-lf-crlf-and-autodetect/0048/expout
index 686f30737..a619474e4 100644
--- a/test/cases/io-lf-crlf-and-autodetect/0048/expout
+++ b/test/cases/io-lf-crlf-and-autodetect/0048/expout
@@ -1,66 +1,67 @@
+[
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": "eks",
   "b": "pan",
   "i": 2,
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
-}
+},
 {
   "a": "wye",
   "b": "wye",
   "i": 3,
   "x": 0.20460330576630303,
   "y": 0.33831852551664776
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "i": 4,
   "x": 0.38139939387114097,
   "y": 0.13418874328430463
-}
+},
 {
   "a": "wye",
   "b": "pan",
   "i": 5,
   "x": 0.5732889198020006,
   "y": 0.8636244699032729
-}
+},
 {
   "a": "zee",
   "b": "pan",
   "i": 6,
   "x": 0.5271261600918548,
   "y": 0.49322128674835697
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "i": 7,
   "x": 0.6117840605678454,
   "y": 0.1878849191181694
-}
+},
 {
   "a": "zee",
   "b": "wye",
   "i": 8,
   "x": 0.5985540091064224,
   "y": 0.976181385699006
-}
+},
 {
   "a": "hat",
   "b": "wye",
   "i": 9,
   "x": 0.03144187646093577,
   "y": 0.7495507603507059
-}
+},
 {
   "a": "pan",
   "b": "wye",
@@ -68,3 +69,4 @@
   "x": 0.5026260055412137,
   "y": 0.9526183602969864
 }
+]
diff --git a/test/cases/io-lf-crlf-and-autodetect/0053/expout b/test/cases/io-lf-crlf-and-autodetect/0053/expout
index 686f30737..a619474e4 100644
--- a/test/cases/io-lf-crlf-and-autodetect/0053/expout
+++ b/test/cases/io-lf-crlf-and-autodetect/0053/expout
@@ -1,66 +1,67 @@
+[
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": "eks",
   "b": "pan",
   "i": 2,
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
-}
+},
 {
   "a": "wye",
   "b": "wye",
   "i": 3,
   "x": 0.20460330576630303,
   "y": 0.33831852551664776
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "i": 4,
   "x": 0.38139939387114097,
   "y": 0.13418874328430463
-}
+},
 {
   "a": "wye",
   "b": "pan",
   "i": 5,
   "x": 0.5732889198020006,
   "y": 0.8636244699032729
-}
+},
 {
   "a": "zee",
   "b": "pan",
   "i": 6,
   "x": 0.5271261600918548,
   "y": 0.49322128674835697
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "i": 7,
   "x": 0.6117840605678454,
   "y": 0.1878849191181694
-}
+},
 {
   "a": "zee",
   "b": "wye",
   "i": 8,
   "x": 0.5985540091064224,
   "y": 0.976181385699006
-}
+},
 {
   "a": "hat",
   "b": "wye",
   "i": 9,
   "x": 0.03144187646093577,
   "y": 0.7495507603507059
-}
+},
 {
   "a": "pan",
   "b": "wye",
@@ -68,3 +69,4 @@
   "x": 0.5026260055412137,
   "y": 0.9526183602969864
 }
+]
diff --git a/test/cases/io-lf-crlf-and-autodetect/0054/expout b/test/cases/io-lf-crlf-and-autodetect/0054/expout
index 686f30737..a619474e4 100644
--- a/test/cases/io-lf-crlf-and-autodetect/0054/expout
+++ b/test/cases/io-lf-crlf-and-autodetect/0054/expout
@@ -1,66 +1,67 @@
+[
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": "eks",
   "b": "pan",
   "i": 2,
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
-}
+},
 {
   "a": "wye",
   "b": "wye",
   "i": 3,
   "x": 0.20460330576630303,
   "y": 0.33831852551664776
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "i": 4,
   "x": 0.38139939387114097,
   "y": 0.13418874328430463
-}
+},
 {
   "a": "wye",
   "b": "pan",
   "i": 5,
   "x": 0.5732889198020006,
   "y": 0.8636244699032729
-}
+},
 {
   "a": "zee",
   "b": "pan",
   "i": 6,
   "x": 0.5271261600918548,
   "y": 0.49322128674835697
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "i": 7,
   "x": 0.6117840605678454,
   "y": 0.1878849191181694
-}
+},
 {
   "a": "zee",
   "b": "wye",
   "i": 8,
   "x": 0.5985540091064224,
   "y": 0.976181385699006
-}
+},
 {
   "a": "hat",
   "b": "wye",
   "i": 9,
   "x": 0.03144187646093577,
   "y": 0.7495507603507059
-}
+},
 {
   "a": "pan",
   "b": "wye",
@@ -68,3 +69,4 @@
   "x": 0.5026260055412137,
   "y": 0.9526183602969864
 }
+]
diff --git a/test/cases/io-lf-crlf-and-autodetect/0055/expout b/test/cases/io-lf-crlf-and-autodetect/0055/expout
index 686f30737..a619474e4 100644
--- a/test/cases/io-lf-crlf-and-autodetect/0055/expout
+++ b/test/cases/io-lf-crlf-and-autodetect/0055/expout
@@ -1,66 +1,67 @@
+[
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": "eks",
   "b": "pan",
   "i": 2,
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
-}
+},
 {
   "a": "wye",
   "b": "wye",
   "i": 3,
   "x": 0.20460330576630303,
   "y": 0.33831852551664776
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "i": 4,
   "x": 0.38139939387114097,
   "y": 0.13418874328430463
-}
+},
 {
   "a": "wye",
   "b": "pan",
   "i": 5,
   "x": 0.5732889198020006,
   "y": 0.8636244699032729
-}
+},
 {
   "a": "zee",
   "b": "pan",
   "i": 6,
   "x": 0.5271261600918548,
   "y": 0.49322128674835697
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "i": 7,
   "x": 0.6117840605678454,
   "y": 0.1878849191181694
-}
+},
 {
   "a": "zee",
   "b": "wye",
   "i": 8,
   "x": 0.5985540091064224,
   "y": 0.976181385699006
-}
+},
 {
   "a": "hat",
   "b": "wye",
   "i": 9,
   "x": 0.03144187646093577,
   "y": 0.7495507603507059
-}
+},
 {
   "a": "pan",
   "b": "wye",
@@ -68,3 +69,4 @@
   "x": 0.5026260055412137,
   "y": 0.9526183602969864
 }
+]
diff --git a/test/cases/io-lf-crlf-and-autodetect/0056/expout b/test/cases/io-lf-crlf-and-autodetect/0056/expout
index 686f30737..a619474e4 100644
--- a/test/cases/io-lf-crlf-and-autodetect/0056/expout
+++ b/test/cases/io-lf-crlf-and-autodetect/0056/expout
@@ -1,66 +1,67 @@
+[
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": "eks",
   "b": "pan",
   "i": 2,
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
-}
+},
 {
   "a": "wye",
   "b": "wye",
   "i": 3,
   "x": 0.20460330576630303,
   "y": 0.33831852551664776
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "i": 4,
   "x": 0.38139939387114097,
   "y": 0.13418874328430463
-}
+},
 {
   "a": "wye",
   "b": "pan",
   "i": 5,
   "x": 0.5732889198020006,
   "y": 0.8636244699032729
-}
+},
 {
   "a": "zee",
   "b": "pan",
   "i": 6,
   "x": 0.5271261600918548,
   "y": 0.49322128674835697
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "i": 7,
   "x": 0.6117840605678454,
   "y": 0.1878849191181694
-}
+},
 {
   "a": "zee",
   "b": "wye",
   "i": 8,
   "x": 0.5985540091064224,
   "y": 0.976181385699006
-}
+},
 {
   "a": "hat",
   "b": "wye",
   "i": 9,
   "x": 0.03144187646093577,
   "y": 0.7495507603507059
-}
+},
 {
   "a": "pan",
   "b": "wye",
@@ -68,3 +69,4 @@
   "x": 0.5026260055412137,
   "y": 0.9526183602969864
 }
+]
diff --git a/test/cases/io-multi/0009/expout b/test/cases/io-multi/0009/expout
index e8299a656..36b73b3b7 100644
--- a/test/cases/io-multi/0009/expout
+++ b/test/cases/io-multi/0009/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -8,7 +9,7 @@
   "nr": 1,
   "fnr": 1,
   "filenum": 1
-}
+},
 {
   "a": "eks",
   "b": "pan",
@@ -19,7 +20,7 @@
   "nr": 2,
   "fnr": 2,
   "filenum": 1
-}
+},
 {
   "a": "wye",
   "b": "wye",
@@ -30,7 +31,7 @@
   "nr": 3,
   "fnr": 3,
   "filenum": 1
-}
+},
 {
   "a": "eks",
   "b": "wye",
@@ -41,7 +42,7 @@
   "nr": 4,
   "fnr": 4,
   "filenum": 1
-}
+},
 {
   "a": "wye",
   "b": "pan",
@@ -52,7 +53,7 @@
   "nr": 5,
   "fnr": 1,
   "filenum": 2
-}
+},
 {
   "a": "zee",
   "b": "pan",
@@ -63,7 +64,7 @@
   "nr": 6,
   "fnr": 2,
   "filenum": 2
-}
+},
 {
   "a": "eks",
   "b": "zee",
@@ -75,3 +76,4 @@
   "fnr": 3,
   "filenum": 2
 }
+]
diff --git a/test/cases/io-multi/0032/expout b/test/cases/io-multi/0032/expout
index 2c5d634b5..a1a35ce1d 100644
--- a/test/cases/io-multi/0032/expout
+++ b/test/cases/io-multi/0032/expout
@@ -1,24 +1,25 @@
+[
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": "eks",
   "b": "pan",
   "i": 2,
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
-}
+},
 {
   "a": "wye",
   "b": "wye",
   "i": 3,
   "x": 0.20460330576630303,
   "y": 0.33831852551664776
-}
+},
 {
   "a": "eks",
   "b": "wye",
@@ -26,3 +27,4 @@
   "x": 0.38139939387114097,
   "y": 0.13418874328430463
 }
+]
diff --git a/test/cases/io-multi/0035/expout b/test/cases/io-multi/0035/expout
index 8f1f33066..0df6c420a 100644
--- a/test/cases/io-multi/0035/expout
+++ b/test/cases/io-multi/0035/expout
@@ -1,5 +1,7 @@
+[
 {
   "a": "d",
   "b": "e",
   "c": "f"
 }
+]
diff --git a/test/cases/io-multi/0036/expout b/test/cases/io-multi/0036/expout
index 577d8bcc1..41d246a7f 100644
--- a/test/cases/io-multi/0036/expout
+++ b/test/cases/io-multi/0036/expout
@@ -1,10 +1,12 @@
+[
 {
   "1": "a",
   "2": "b",
   "3": "c"
-}
+},
 {
   "1": "d",
   "2": "e",
   "3": "f"
 }
+]
diff --git a/test/cases/io-multi/0037/expout b/test/cases/io-multi/0037/expout
index 2c5d634b5..a1a35ce1d 100644
--- a/test/cases/io-multi/0037/expout
+++ b/test/cases/io-multi/0037/expout
@@ -1,24 +1,25 @@
+[
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": "eks",
   "b": "pan",
   "i": 2,
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
-}
+},
 {
   "a": "wye",
   "b": "wye",
   "i": 3,
   "x": 0.20460330576630303,
   "y": 0.33831852551664776
-}
+},
 {
   "a": "eks",
   "b": "wye",
@@ -26,3 +27,4 @@
   "x": 0.38139939387114097,
   "y": 0.13418874328430463
 }
+]
diff --git a/test/cases/io-multi/0038/expout b/test/cases/io-multi/0038/expout
index 577d8bcc1..41d246a7f 100644
--- a/test/cases/io-multi/0038/expout
+++ b/test/cases/io-multi/0038/expout
@@ -1,10 +1,12 @@
+[
 {
   "1": "a",
   "2": "b",
   "3": "c"
-}
+},
 {
   "1": "d",
   "2": "e",
   "3": "f"
 }
+]
diff --git a/test/cases/io-multi/0043/expout b/test/cases/io-multi/0043/expout
index 96db73c03..d641fc4fe 100644
--- a/test/cases/io-multi/0043/expout
+++ b/test/cases/io-multi/0043/expout
@@ -1,15 +1,17 @@
+[
 {
   "a": 1,
   "b": 2,
   "c": 3
-}
+},
 {
   "a": 4,
   "b": 5,
   "c": ""
-}
+},
 {
   "a": 6,
   "b": 7,
   "c": 8
 }
+]
diff --git a/test/cases/io-multi/0044/expout b/test/cases/io-multi/0044/expout
index 6029a564e..5febba45a 100644
--- a/test/cases/io-multi/0044/expout
+++ b/test/cases/io-multi/0044/expout
@@ -1,16 +1,18 @@
+[
 {
   "a": 1,
   "b": 2,
   "c": 3
-}
+},
 {
   "a": 4,
   "b": 5,
   "c": 6,
   "4": 7
-}
+},
 {
   "a": 8,
   "b": 9,
   "c": 10
 }
+]
diff --git a/test/cases/io-multi/0045/expout b/test/cases/io-multi/0045/expout
index 96db73c03..d641fc4fe 100644
--- a/test/cases/io-multi/0045/expout
+++ b/test/cases/io-multi/0045/expout
@@ -1,15 +1,17 @@
+[
 {
   "a": 1,
   "b": 2,
   "c": 3
-}
+},
 {
   "a": 4,
   "b": 5,
   "c": ""
-}
+},
 {
   "a": 6,
   "b": 7,
   "c": 8
 }
+]
diff --git a/test/cases/io-multi/0046/expout b/test/cases/io-multi/0046/expout
index 6029a564e..5febba45a 100644
--- a/test/cases/io-multi/0046/expout
+++ b/test/cases/io-multi/0046/expout
@@ -1,16 +1,18 @@
+[
 {
   "a": 1,
   "b": 2,
   "c": 3
-}
+},
 {
   "a": 4,
   "b": 5,
   "c": 6,
   "4": 7
-}
+},
 {
   "a": 8,
   "b": 9,
   "c": 10
 }
+]
diff --git a/test/cases/io-multi/0047/expout b/test/cases/io-multi/0047/expout
index 9fd9ba0f8..ed00e4449 100644
--- a/test/cases/io-multi/0047/expout
+++ b/test/cases/io-multi/0047/expout
@@ -1,10 +1,12 @@
+[
 {
   "a": 1,
   "b": 2,
   "c": 3
-}
+},
 {
   "d": "4 5 6 7",
   "e": "",
   "f": 8
 }
+]
diff --git a/test/cases/io-multi/0048/expout b/test/cases/io-multi/0048/expout
index e9a1b29f0..79f9dd2ae 100644
--- a/test/cases/io-multi/0048/expout
+++ b/test/cases/io-multi/0048/expout
@@ -1,10 +1,12 @@
+[
 {
   "a": 1,
   "b": 2,
   "c": 3
-}
+},
 {
   "a": 4,
   "b": 5,
   "c": 6
 }
+]
diff --git a/test/cases/io-multi/0049/expout b/test/cases/io-multi/0049/expout
index 83090e37a..d18faa578 100644
--- a/test/cases/io-multi/0049/expout
+++ b/test/cases/io-multi/0049/expout
@@ -1,5 +1,7 @@
+[
 {
   "a": 1,
   "": "b 2",
   "c": 3
 }
+]
diff --git a/test/cases/io-multi/0050/expout b/test/cases/io-multi/0050/expout
index a2747a200..bab712eb5 100644
--- a/test/cases/io-multi/0050/expout
+++ b/test/cases/io-multi/0050/expout
@@ -1,20 +1,22 @@
+[
 {
   "a": 1,
   "b": 2,
   "c": 3
-}
+},
 {
   "d": "4 5 6 7",
   "e": "",
   "f": 8
-}
+},
 {
   "a": 1,
   "b": 2,
   "c": 3
-}
+},
 {
   "a": 4,
   "b": 5,
   "c": 6
 }
+]
diff --git a/test/cases/io-multi/0051/expout b/test/cases/io-multi/0051/expout
index 7e0af4909..5139419ae 100644
--- a/test/cases/io-multi/0051/expout
+++ b/test/cases/io-multi/0051/expout
@@ -1,20 +1,22 @@
+[
 {
   "a": 1,
   "b": 2,
   "c": 3
-}
+},
 {
   "a": 4,
   "b": 5,
   "c": 6
-}
+},
 {
   "a": 1,
   "b": 2,
   "c": 3
-}
+},
 {
   "d": "4 5 6 7",
   "e": "",
   "f": 8
 }
+]
diff --git a/test/cases/io-multi/0052/expout b/test/cases/io-multi/0052/expout
index 255169d28..ae7d4b59f 100644
--- a/test/cases/io-multi/0052/expout
+++ b/test/cases/io-multi/0052/expout
@@ -1,25 +1,27 @@
+[
 {
   "a": 1,
   "b": 2,
   "c": 3
-}
+},
 {
   "d": "4 5 6 7",
   "e": "",
   "f": 8
-}
+},
 {
   "a": 1,
   "b": 2,
   "c": 3
-}
+},
 {
   "a": 4,
   "b": 5,
   "c": 6
-}
+},
 {
   "a": 1,
   "": "b 2",
   "c": 3
 }
+]
diff --git a/test/cases/io-multi/0053/expout b/test/cases/io-multi/0053/expout
index e69de29bb..0d4f101c7 100644
--- a/test/cases/io-multi/0053/expout
+++ b/test/cases/io-multi/0053/expout
@@ -0,0 +1,2 @@
+[
+]
diff --git a/test/cases/io-multi/0054/expout b/test/cases/io-multi/0054/expout
index 45cf01684..ba0ffb962 100644
--- a/test/cases/io-multi/0054/expout
+++ b/test/cases/io-multi/0054/expout
@@ -1,3 +1,4 @@
+[
 {
   "a": "pan",
   "b": "pan",
@@ -5,3 +6,4 @@
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
 }
+]
diff --git a/test/cases/io-multi/0055/expout b/test/cases/io-multi/0055/expout
index a2976ece6..091d0ff00 100644
--- a/test/cases/io-multi/0055/expout
+++ b/test/cases/io-multi/0055/expout
@@ -1,10 +1,11 @@
+[
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": "eks",
   "b": "pan",
@@ -12,3 +13,4 @@
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
 }
+]
diff --git a/test/cases/io-multi/0056/expout b/test/cases/io-multi/0056/expout
index 2ac590272..02139aa53 100644
--- a/test/cases/io-multi/0056/expout
+++ b/test/cases/io-multi/0056/expout
@@ -1,17 +1,18 @@
+[
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": "eks",
   "b": "pan",
   "i": 2,
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
-}
+},
 {
   "a": "wye",
   "b": "wye",
@@ -19,3 +20,4 @@
   "x": 0.20460330576630303,
   "y": 0.33831852551664776
 }
+]
diff --git a/test/cases/io-separator-aliases/0001/expout b/test/cases/io-separator-aliases/0001/expout
index 1b55d791d..1cfb35be2 100644
--- a/test/cases/io-separator-aliases/0001/expout
+++ b/test/cases/io-separator-aliases/0001/expout
@@ -1,20 +1,22 @@
+[
+{
+  "1": "a",
+  "2": "b",
+  "3": "c"
+},
+{
+  "1": "a",
+  "2": "b",
+  "3": "c"
+},
+{
+  "1": "a",
+  "2": "b",
+  "3": "c"
+},
 {
   "1": "a",
   "2": "b",
   "3": "c"
 }
-{
-  "1": "a",
-  "2": "b",
-  "3": "c"
-}
-{
-  "1": "a",
-  "2": "b",
-  "3": "c"
-}
-{
-  "1": "a",
-  "2": "b",
-  "3": "c"
-}
+]
diff --git a/test/cases/io-separator-aliases/0002/expout b/test/cases/io-separator-aliases/0002/expout
index 58c249a18..b4dcbce3a 100644
--- a/test/cases/io-separator-aliases/0002/expout
+++ b/test/cases/io-separator-aliases/0002/expout
@@ -1,18 +1,19 @@
+[
 {
   "1": "a\tb",
   "2": "c"
-}
+},
 {
   "1": "a",
   "2": "b\tc"
-}
+},
 {
   "1": "a\t\t\tb",
   "2": "",
   "3": "",
   "4": "",
   "5": "c"
-}
+},
 {
   "1": "a\t\t",
   "2": "\tb",
@@ -21,3 +22,4 @@
   "5": "",
   "6": "c"
 }
+]
diff --git a/test/cases/io-separator-aliases/0003/expout b/test/cases/io-separator-aliases/0003/expout
index f8b2c1be5..ff11da711 100644
--- a/test/cases/io-separator-aliases/0003/expout
+++ b/test/cases/io-separator-aliases/0003/expout
@@ -1,18 +1,20 @@
+[
 {
   "1": "a\tb",
   "2": "c"
-}
+},
 {
   "1": "a",
   "2": "b\tc"
-}
+},
 {
   "1": "a\t\t\tb",
   "2": "c"
-}
+},
 {
   "1": "a\t\t",
   "2": "\tb",
   "3": "\t",
   "4": "c"
 }
+]
diff --git a/test/cases/io-separator-aliases/0004/expout b/test/cases/io-separator-aliases/0004/expout
index 25703f986..064fb4756 100644
--- a/test/cases/io-separator-aliases/0004/expout
+++ b/test/cases/io-separator-aliases/0004/expout
@@ -1,17 +1,18 @@
+[
 {
   "1": "a",
   "2": "b c"
-}
+},
 {
   "1": "a b",
   "2": "c"
-}
+},
 {
   "1": "a",
   "2": "",
   "3": "",
   "4": "b    c"
-}
+},
 {
   "1": "a",
   "2": "",
@@ -19,3 +20,4 @@
   "4": "b  ",
   "5": "  c"
 }
+]
diff --git a/test/cases/io-separator-aliases/0005/expout b/test/cases/io-separator-aliases/0005/expout
index dca9b8a13..ec1493890 100644
--- a/test/cases/io-separator-aliases/0005/expout
+++ b/test/cases/io-separator-aliases/0005/expout
@@ -1,18 +1,20 @@
+[
 {
   "1": "a",
   "2": "b c"
-}
+},
 {
   "1": "a b",
   "2": "c"
-}
+},
 {
   "1": "a",
   "2": "b    c"
-}
+},
 {
   "1": "a",
   "2": " ",
   "3": "b  ",
   "4": "  c"
 }
+]
diff --git a/test/cases/io-separator-aliases/0006/expout b/test/cases/io-separator-aliases/0006/expout
index 1b55d791d..1cfb35be2 100644
--- a/test/cases/io-separator-aliases/0006/expout
+++ b/test/cases/io-separator-aliases/0006/expout
@@ -1,20 +1,22 @@
+[
+{
+  "1": "a",
+  "2": "b",
+  "3": "c"
+},
+{
+  "1": "a",
+  "2": "b",
+  "3": "c"
+},
+{
+  "1": "a",
+  "2": "b",
+  "3": "c"
+},
 {
   "1": "a",
   "2": "b",
   "3": "c"
 }
-{
-  "1": "a",
-  "2": "b",
-  "3": "c"
-}
-{
-  "1": "a",
-  "2": "b",
-  "3": "c"
-}
-{
-  "1": "a",
-  "2": "b",
-  "3": "c"
-}
+]
diff --git a/test/cases/io-skip-pass-comments/0036-buffer-split/expout b/test/cases/io-skip-pass-comments/0036-buffer-split/expout
index ccdb97fc4..4f50430f7 100644
--- a/test/cases/io-skip-pass-comments/0036-buffer-split/expout
+++ b/test/cases/io-skip-pass-comments/0036-buffer-split/expout
@@ -1,4 +1,6 @@
+[
 {
   "a": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
   "b": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
 }
+]
diff --git a/test/cases/output-colorization/0001/expout b/test/cases/output-colorization/0001/expout
index 686f30737..a619474e4 100644
--- a/test/cases/output-colorization/0001/expout
+++ b/test/cases/output-colorization/0001/expout
@@ -1,66 +1,67 @@
+[
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": "eks",
   "b": "pan",
   "i": 2,
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
-}
+},
 {
   "a": "wye",
   "b": "wye",
   "i": 3,
   "x": 0.20460330576630303,
   "y": 0.33831852551664776
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "i": 4,
   "x": 0.38139939387114097,
   "y": 0.13418874328430463
-}
+},
 {
   "a": "wye",
   "b": "pan",
   "i": 5,
   "x": 0.5732889198020006,
   "y": 0.8636244699032729
-}
+},
 {
   "a": "zee",
   "b": "pan",
   "i": 6,
   "x": 0.5271261600918548,
   "y": 0.49322128674835697
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "i": 7,
   "x": 0.6117840605678454,
   "y": 0.1878849191181694
-}
+},
 {
   "a": "zee",
   "b": "wye",
   "i": 8,
   "x": 0.5985540091064224,
   "y": 0.976181385699006
-}
+},
 {
   "a": "hat",
   "b": "wye",
   "i": 9,
   "x": 0.03144187646093577,
   "y": 0.7495507603507059
-}
+},
 {
   "a": "pan",
   "b": "wye",
@@ -68,3 +69,4 @@
   "x": 0.5026260055412137,
   "y": 0.9526183602969864
 }
+]
diff --git a/test/cases/output-colorization/0002/expout b/test/cases/output-colorization/0002/expout
index 3dd4a433e..c7ad10630 100644
--- a/test/cases/output-colorization/0002/expout
+++ b/test/cases/output-colorization/0002/expout
@@ -1,66 +1,67 @@
+[
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "x": 0.3467901443380824,
   "y": 0.7268028627434533
-}
+},
 {
   "a": "eks",
   "b": "pan",
   "i": 2,
   "x": 0.7586799647899636,
   "y": 0.5221511083334797
-}
+},
 {
   "a": "wye",
   "b": "wye",
   "i": 3,
   "x": 0.20460330576630303,
   "y": 0.33831852551664776
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "i": 4,
   "x": 0.38139939387114097,
   "y": 0.13418874328430463
-}
+},
 {
   "a": "wye",
   "b": "pan",
   "i": 5,
   "x": 0.5732889198020006,
   "y": 0.8636244699032729
-}
+},
 {
   "a": "zee",
   "b": "pan",
   "i": 6,
   "x": 0.5271261600918548,
   "y": 0.49322128674835697
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "i": 7,
   "x": 0.6117840605678454,
   "y": 0.1878849191181694
-}
+},
 {
   "a": "zee",
   "b": "wye",
   "i": 8,
   "x": 0.5985540091064224,
   "y": 0.976181385699006
-}
+},
 {
   "a": "hat",
   "b": "wye",
   "i": 9,
   "x": 0.03144187646093577,
   "y": 0.7495507603507059
-}
+},
 {
   "a": "pan",
   "b": "wye",
@@ -68,3 +69,4 @@
   "x": 0.5026260055412137,
   "y": 0.9526183602969864
 }
+]
diff --git a/test/cases/repl/0007/expout b/test/cases/repl/0007/expout
index 5ff356688..0ef9c49db 100644
--- a/test/cases/repl/0007/expout
+++ b/test/cases/repl/0007/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -24,5 +25,6 @@
     "empty3": {},
     "emtpy4": []
   }
-}
-End of record stream
+}End of record stream
+
+]
diff --git a/test/cases/repl/0009/expout b/test/cases/repl/0009/expout
index 5ff356688..0ef9c49db 100644
--- a/test/cases/repl/0009/expout
+++ b/test/cases/repl/0009/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -24,5 +25,6 @@
     "empty3": {},
     "emtpy4": []
   }
-}
-End of record stream
+}End of record stream
+
+]
diff --git a/test/cases/repl/0010/expout b/test/cases/repl/0010/expout
index 9808817df..92f93309d 100644
--- a/test/cases/repl/0010/expout
+++ b/test/cases/repl/0010/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -24,8 +25,10 @@
     "empty3": {},
     "emtpy4": []
   }
-}
-End of record stream
+}End of record stream
+
+]
+,
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -52,5 +55,6 @@ End of record stream
     "empty3": {},
     "emtpy4": []
   }
-}
-End of record stream
+}End of record stream
+
+]
diff --git a/test/cases/verb-flatten-unflatten/0004/expout b/test/cases/verb-flatten-unflatten/0004/expout
index ae0fb02c8..1bb3b80bc 100644
--- a/test/cases/verb-flatten-unflatten/0004/expout
+++ b/test/cases/verb-flatten-unflatten/0004/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -21,3 +22,4 @@
     "emtpy4": []
   }
 }
+]
diff --git a/test/cases/verb-flatten-unflatten/0005/expout b/test/cases/verb-flatten-unflatten/0005/expout
index c74f4a6b7..dd6a3524c 100644
--- a/test/cases/verb-flatten-unflatten/0005/expout
+++ b/test/cases/verb-flatten-unflatten/0005/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -21,3 +22,4 @@
     "emtpy4": []
   }
 }
+]
diff --git a/test/cases/verb-flatten-unflatten/0008/expout b/test/cases/verb-flatten-unflatten/0008/expout
index 0a3d2cfeb..9a45bc186 100644
--- a/test/cases/verb-flatten-unflatten/0008/expout
+++ b/test/cases/verb-flatten-unflatten/0008/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -25,3 +26,4 @@
     "emtpy4": []
   }
 }
+]
diff --git a/test/cases/verb-flatten-unflatten/0009/expout b/test/cases/verb-flatten-unflatten/0009/expout
index 0a3d2cfeb..9a45bc186 100644
--- a/test/cases/verb-flatten-unflatten/0009/expout
+++ b/test/cases/verb-flatten-unflatten/0009/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -25,3 +26,4 @@
     "emtpy4": []
   }
 }
+]
diff --git a/test/cases/verb-flatten-unflatten/0010/expout b/test/cases/verb-flatten-unflatten/0010/expout
index 0a3d2cfeb..9a45bc186 100644
--- a/test/cases/verb-flatten-unflatten/0010/expout
+++ b/test/cases/verb-flatten-unflatten/0010/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -25,3 +26,4 @@
     "emtpy4": []
   }
 }
+]
diff --git a/test/cases/verb-flatten-unflatten/0011/expout b/test/cases/verb-flatten-unflatten/0011/expout
index 0a3d2cfeb..9a45bc186 100644
--- a/test/cases/verb-flatten-unflatten/0011/expout
+++ b/test/cases/verb-flatten-unflatten/0011/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -25,3 +26,4 @@
     "emtpy4": []
   }
 }
+]
diff --git a/test/cases/verb-flatten-unflatten/0013/expout b/test/cases/verb-flatten-unflatten/0013/expout
index 0a3d2cfeb..9a45bc186 100644
--- a/test/cases/verb-flatten-unflatten/0013/expout
+++ b/test/cases/verb-flatten-unflatten/0013/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -25,3 +26,4 @@
     "emtpy4": []
   }
 }
+]
diff --git a/test/cases/verb-flatten-unflatten/0014/expout b/test/cases/verb-flatten-unflatten/0014/expout
index 0a3d2cfeb..9a45bc186 100644
--- a/test/cases/verb-flatten-unflatten/0014/expout
+++ b/test/cases/verb-flatten-unflatten/0014/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -25,3 +26,4 @@
     "emtpy4": []
   }
 }
+]
diff --git a/test/cases/verb-flatten-unflatten/0015/expout b/test/cases/verb-flatten-unflatten/0015/expout
index 0a3d2cfeb..9a45bc186 100644
--- a/test/cases/verb-flatten-unflatten/0015/expout
+++ b/test/cases/verb-flatten-unflatten/0015/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -25,3 +26,4 @@
     "emtpy4": []
   }
 }
+]
diff --git a/test/cases/verb-flatten-unflatten/0016/expout b/test/cases/verb-flatten-unflatten/0016/expout
index 0a3d2cfeb..9a45bc186 100644
--- a/test/cases/verb-flatten-unflatten/0016/expout
+++ b/test/cases/verb-flatten-unflatten/0016/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -25,3 +26,4 @@
     "emtpy4": []
   }
 }
+]
diff --git a/test/cases/verb-flatten-unflatten/0018/expout b/test/cases/verb-flatten-unflatten/0018/expout
index 0a3d2cfeb..9a45bc186 100644
--- a/test/cases/verb-flatten-unflatten/0018/expout
+++ b/test/cases/verb-flatten-unflatten/0018/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -25,3 +26,4 @@
     "emtpy4": []
   }
 }
+]
diff --git a/test/cases/verb-format-values/0003/expout b/test/cases/verb-format-values/0003/expout
index 4410f99c4..06216b5ca 100644
--- a/test/cases/verb-format-values/0003/expout
+++ b/test/cases/verb-format-values/0003/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "localhost",
   "pid": 0x3039,
@@ -25,3 +26,4 @@
     "emtpy4": []
   }
 }
+]
diff --git a/test/cases/verb-join-mixed-format/0001/expout b/test/cases/verb-join-mixed-format/0001/expout
index 0c9c682a2..f705c9a6d 100644
--- a/test/cases/verb-join-mixed-format/0001/expout
+++ b/test/cases/verb-join-mixed-format/0001/expout
@@ -1,20 +1,22 @@
+[
 {
   "x": 1,
   "a": 2,
   "b": 20
-}
+},
 {
   "x": 2,
   "a": 3,
   "b": 30
-}
+},
 {
   "x": 3,
   "a": 4,
   "b": 40
-}
+},
 {
   "x": 4,
   "a": 5,
   "b": 50
 }
+]
diff --git a/test/cases/verb-join-mixed-format/0004/expout b/test/cases/verb-join-mixed-format/0004/expout
index 0c9c682a2..f705c9a6d 100644
--- a/test/cases/verb-join-mixed-format/0004/expout
+++ b/test/cases/verb-join-mixed-format/0004/expout
@@ -1,20 +1,22 @@
+[
 {
   "x": 1,
   "a": 2,
   "b": 20
-}
+},
 {
   "x": 2,
   "a": 3,
   "b": 30
-}
+},
 {
   "x": 3,
   "a": 4,
   "b": 40
-}
+},
 {
   "x": 4,
   "a": 5,
   "b": 50
 }
+]
diff --git a/test/cases/verb-join-mixed-format/0007/expout b/test/cases/verb-join-mixed-format/0007/expout
index 0c9c682a2..f705c9a6d 100644
--- a/test/cases/verb-join-mixed-format/0007/expout
+++ b/test/cases/verb-join-mixed-format/0007/expout
@@ -1,20 +1,22 @@
+[
 {
   "x": 1,
   "a": 2,
   "b": 20
-}
+},
 {
   "x": 2,
   "a": 3,
   "b": 30
-}
+},
 {
   "x": 3,
   "a": 4,
   "b": 40
-}
+},
 {
   "x": 4,
   "a": 5,
   "b": 50
 }
+]
diff --git a/test/cases/verb-join-mixed-format/0010/expout b/test/cases/verb-join-mixed-format/0010/expout
index 0c9c682a2..f705c9a6d 100644
--- a/test/cases/verb-join-mixed-format/0010/expout
+++ b/test/cases/verb-join-mixed-format/0010/expout
@@ -1,20 +1,22 @@
+[
 {
   "x": 1,
   "a": 2,
   "b": 20
-}
+},
 {
   "x": 2,
   "a": 3,
   "b": 30
-}
+},
 {
   "x": 3,
   "a": 4,
   "b": 40
-}
+},
 {
   "x": 4,
   "a": 5,
   "b": 50
 }
+]
diff --git a/test/cases/verb-join-mixed-format/0013/expout b/test/cases/verb-join-mixed-format/0013/expout
index 0c9c682a2..f705c9a6d 100644
--- a/test/cases/verb-join-mixed-format/0013/expout
+++ b/test/cases/verb-join-mixed-format/0013/expout
@@ -1,20 +1,22 @@
+[
 {
   "x": 1,
   "a": 2,
   "b": 20
-}
+},
 {
   "x": 2,
   "a": 3,
   "b": 30
-}
+},
 {
   "x": 3,
   "a": 4,
   "b": 40
-}
+},
 {
   "x": 4,
   "a": 5,
   "b": 50
 }
+]
diff --git a/test/cases/verb-join-mixed-format/0016/expout b/test/cases/verb-join-mixed-format/0016/expout
index 0c9c682a2..f705c9a6d 100644
--- a/test/cases/verb-join-mixed-format/0016/expout
+++ b/test/cases/verb-join-mixed-format/0016/expout
@@ -1,20 +1,22 @@
+[
 {
   "x": 1,
   "a": 2,
   "b": 20
-}
+},
 {
   "x": 2,
   "a": 3,
   "b": 30
-}
+},
 {
   "x": 3,
   "a": 4,
   "b": 40
-}
+},
 {
   "x": 4,
   "a": 5,
   "b": 50
 }
+]
diff --git a/test/cases/verb-join-mixed-format/0019/expout b/test/cases/verb-join-mixed-format/0019/expout
index 0c9c682a2..f705c9a6d 100644
--- a/test/cases/verb-join-mixed-format/0019/expout
+++ b/test/cases/verb-join-mixed-format/0019/expout
@@ -1,20 +1,22 @@
+[
 {
   "x": 1,
   "a": 2,
   "b": 20
-}
+},
 {
   "x": 2,
   "a": 3,
   "b": 30
-}
+},
 {
   "x": 3,
   "a": 4,
   "b": 40
-}
+},
 {
   "x": 4,
   "a": 5,
   "b": 50
 }
+]
diff --git a/test/cases/verb-join-mixed-format/0022/expout b/test/cases/verb-join-mixed-format/0022/expout
index 0c9c682a2..f705c9a6d 100644
--- a/test/cases/verb-join-mixed-format/0022/expout
+++ b/test/cases/verb-join-mixed-format/0022/expout
@@ -1,20 +1,22 @@
+[
 {
   "x": 1,
   "a": 2,
   "b": 20
-}
+},
 {
   "x": 2,
   "a": 3,
   "b": 30
-}
+},
 {
   "x": 3,
   "a": 4,
   "b": 40
-}
+},
 {
   "x": 4,
   "a": 5,
   "b": 50
 }
+]
diff --git a/test/cases/verb-join-mixed-format/0025/expout b/test/cases/verb-join-mixed-format/0025/expout
index 0c9c682a2..f705c9a6d 100644
--- a/test/cases/verb-join-mixed-format/0025/expout
+++ b/test/cases/verb-join-mixed-format/0025/expout
@@ -1,20 +1,22 @@
+[
 {
   "x": 1,
   "a": 2,
   "b": 20
-}
+},
 {
   "x": 2,
   "a": 3,
   "b": 30
-}
+},
 {
   "x": 3,
   "a": 4,
   "b": 40
-}
+},
 {
   "x": 4,
   "a": 5,
   "b": 50
 }
+]
diff --git a/test/cases/verb-join-mixed-format/0026/expout b/test/cases/verb-join-mixed-format/0026/expout
index 0c9c682a2..f705c9a6d 100644
--- a/test/cases/verb-join-mixed-format/0026/expout
+++ b/test/cases/verb-join-mixed-format/0026/expout
@@ -1,20 +1,22 @@
+[
 {
   "x": 1,
   "a": 2,
   "b": 20
-}
+},
 {
   "x": 2,
   "a": 3,
   "b": 30
-}
+},
 {
   "x": 3,
   "a": 4,
   "b": 40
-}
+},
 {
   "x": 4,
   "a": 5,
   "b": 50
 }
+]
diff --git a/test/cases/verb-join-mixed-format/0027/expout b/test/cases/verb-join-mixed-format/0027/expout
index 0c9c682a2..f705c9a6d 100644
--- a/test/cases/verb-join-mixed-format/0027/expout
+++ b/test/cases/verb-join-mixed-format/0027/expout
@@ -1,20 +1,22 @@
+[
 {
   "x": 1,
   "a": 2,
   "b": 20
-}
+},
 {
   "x": 2,
   "a": 3,
   "b": 30
-}
+},
 {
   "x": 3,
   "a": 4,
   "b": 40
-}
+},
 {
   "x": 4,
   "a": 5,
   "b": 50
 }
+]
diff --git a/test/cases/verb-join-mixed-format/0028/expout b/test/cases/verb-join-mixed-format/0028/expout
index 0c9c682a2..f705c9a6d 100644
--- a/test/cases/verb-join-mixed-format/0028/expout
+++ b/test/cases/verb-join-mixed-format/0028/expout
@@ -1,20 +1,22 @@
+[
 {
   "x": 1,
   "a": 2,
   "b": 20
-}
+},
 {
   "x": 2,
   "a": 3,
   "b": 30
-}
+},
 {
   "x": 3,
   "a": 4,
   "b": 40
-}
+},
 {
   "x": 4,
   "a": 5,
   "b": 50
 }
+]
diff --git a/test/cases/verb-join-mixed-format/0029/expout b/test/cases/verb-join-mixed-format/0029/expout
index 0c9c682a2..f705c9a6d 100644
--- a/test/cases/verb-join-mixed-format/0029/expout
+++ b/test/cases/verb-join-mixed-format/0029/expout
@@ -1,20 +1,22 @@
+[
 {
   "x": 1,
   "a": 2,
   "b": 20
-}
+},
 {
   "x": 2,
   "a": 3,
   "b": 30
-}
+},
 {
   "x": 3,
   "a": 4,
   "b": 40
-}
+},
 {
   "x": 4,
   "a": 5,
   "b": 50
 }
+]
diff --git a/test/cases/verb-join-mixed-format/0030/expout b/test/cases/verb-join-mixed-format/0030/expout
index 0c9c682a2..f705c9a6d 100644
--- a/test/cases/verb-join-mixed-format/0030/expout
+++ b/test/cases/verb-join-mixed-format/0030/expout
@@ -1,20 +1,22 @@
+[
 {
   "x": 1,
   "a": 2,
   "b": 20
-}
+},
 {
   "x": 2,
   "a": 3,
   "b": 30
-}
+},
 {
   "x": 3,
   "a": 4,
   "b": 40
-}
+},
 {
   "x": 4,
   "a": 5,
   "b": 50
 }
+]
diff --git a/test/cases/verb-join-mixed-format/0031/expout b/test/cases/verb-join-mixed-format/0031/expout
index 0c9c682a2..f705c9a6d 100644
--- a/test/cases/verb-join-mixed-format/0031/expout
+++ b/test/cases/verb-join-mixed-format/0031/expout
@@ -1,20 +1,22 @@
+[
 {
   "x": 1,
   "a": 2,
   "b": 20
-}
+},
 {
   "x": 2,
   "a": 3,
   "b": 30
-}
+},
 {
   "x": 3,
   "a": 4,
   "b": 40
-}
+},
 {
   "x": 4,
   "a": 5,
   "b": 50
 }
+]
diff --git a/test/cases/verb-join-mixed-format/0032/expout b/test/cases/verb-join-mixed-format/0032/expout
index 0c9c682a2..f705c9a6d 100644
--- a/test/cases/verb-join-mixed-format/0032/expout
+++ b/test/cases/verb-join-mixed-format/0032/expout
@@ -1,20 +1,22 @@
+[
 {
   "x": 1,
   "a": 2,
   "b": 20
-}
+},
 {
   "x": 2,
   "a": 3,
   "b": 30
-}
+},
 {
   "x": 3,
   "a": 4,
   "b": 40
-}
+},
 {
   "x": 4,
   "a": 5,
   "b": 50
 }
+]
diff --git a/test/cases/verb-join-mixed-format/0033/expout b/test/cases/verb-join-mixed-format/0033/expout
index 0c9c682a2..f705c9a6d 100644
--- a/test/cases/verb-join-mixed-format/0033/expout
+++ b/test/cases/verb-join-mixed-format/0033/expout
@@ -1,20 +1,22 @@
+[
 {
   "x": 1,
   "a": 2,
   "b": 20
-}
+},
 {
   "x": 2,
   "a": 3,
   "b": 30
-}
+},
 {
   "x": 3,
   "a": 4,
   "b": 40
-}
+},
 {
   "x": 4,
   "a": 5,
   "b": 50
 }
+]
diff --git a/test/cases/verb-json-parse-json-stringify/0001/expout b/test/cases/verb-json-parse-json-stringify/0001/expout
index 37f3da5cd..8a0fd5878 100644
--- a/test/cases/verb-json-parse-json-stringify/0001/expout
+++ b/test/cases/verb-json-parse-json-stringify/0001/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "\"localhost\"",
   "pid": "12345",
@@ -7,3 +8,4 @@
   "empty2": "[]",
   "wrapper": "{\"empty3\": {}, \"emtpy4\": []}"
 }
+]
diff --git a/test/cases/verb-json-parse-json-stringify/0003/expout b/test/cases/verb-json-parse-json-stringify/0003/expout
index 261a409ed..8c341fcb7 100644
--- a/test/cases/verb-json-parse-json-stringify/0003/expout
+++ b/test/cases/verb-json-parse-json-stringify/0003/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -16,3 +17,4 @@
     "emtpy4": []
   }
 }
+]
diff --git a/test/cases/verb-json-parse-json-stringify/0005/expout b/test/cases/verb-json-parse-json-stringify/0005/expout
index ee6ab25b8..3336298c7 100644
--- a/test/cases/verb-json-parse-json-stringify/0005/expout
+++ b/test/cases/verb-json-parse-json-stringify/0005/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -16,3 +17,4 @@
     "emtpy4": []
   }
 }
+]
diff --git a/test/cases/verb-json-parse-json-stringify/0006/expout b/test/cases/verb-json-parse-json-stringify/0006/expout
index 261a409ed..8c341fcb7 100644
--- a/test/cases/verb-json-parse-json-stringify/0006/expout
+++ b/test/cases/verb-json-parse-json-stringify/0006/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -16,3 +17,4 @@
     "emtpy4": []
   }
 }
+]
diff --git a/test/cases/verb-json-parse-json-stringify/0007/expout b/test/cases/verb-json-parse-json-stringify/0007/expout
index 37f3da5cd..8a0fd5878 100644
--- a/test/cases/verb-json-parse-json-stringify/0007/expout
+++ b/test/cases/verb-json-parse-json-stringify/0007/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "\"localhost\"",
   "pid": "12345",
@@ -7,3 +8,4 @@
   "empty2": "[]",
   "wrapper": "{\"empty3\": {}, \"emtpy4\": []}"
 }
+]
diff --git a/test/cases/verb-json-parse-json-stringify/0008/expout b/test/cases/verb-json-parse-json-stringify/0008/expout
index 37f3da5cd..8a0fd5878 100644
--- a/test/cases/verb-json-parse-json-stringify/0008/expout
+++ b/test/cases/verb-json-parse-json-stringify/0008/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "\"localhost\"",
   "pid": "12345",
@@ -7,3 +8,4 @@
   "empty2": "[]",
   "wrapper": "{\"empty3\": {}, \"emtpy4\": []}"
 }
+]
diff --git a/test/cases/verb-json-parse-json-stringify/0009/expout b/test/cases/verb-json-parse-json-stringify/0009/expout
index fa6f6da65..f302786e1 100644
--- a/test/cases/verb-json-parse-json-stringify/0009/expout
+++ b/test/cases/verb-json-parse-json-stringify/0009/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "\"localhost\"",
   "pid": "12345",
@@ -7,3 +8,4 @@
   "empty2": "[]",
   "wrapper": "{\n  \"empty3\": {},\n  \"emtpy4\": []\n}"
 }
+]
diff --git a/test/cases/verb-json-parse-json-stringify/0010/expout b/test/cases/verb-json-parse-json-stringify/0010/expout
index fa6f6da65..f302786e1 100644
--- a/test/cases/verb-json-parse-json-stringify/0010/expout
+++ b/test/cases/verb-json-parse-json-stringify/0010/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "\"localhost\"",
   "pid": "12345",
@@ -7,3 +8,4 @@
   "empty2": "[]",
   "wrapper": "{\n  \"empty3\": {},\n  \"emtpy4\": []\n}"
 }
+]
diff --git a/test/cases/verb-json-parse-json-stringify/0011/expout b/test/cases/verb-json-parse-json-stringify/0011/expout
index 37f3da5cd..8a0fd5878 100644
--- a/test/cases/verb-json-parse-json-stringify/0011/expout
+++ b/test/cases/verb-json-parse-json-stringify/0011/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "\"localhost\"",
   "pid": "12345",
@@ -7,3 +8,4 @@
   "empty2": "[]",
   "wrapper": "{\"empty3\": {}, \"emtpy4\": []}"
 }
+]
diff --git a/test/cases/verb-json-parse-json-stringify/0012/expout b/test/cases/verb-json-parse-json-stringify/0012/expout
index 37f3da5cd..8a0fd5878 100644
--- a/test/cases/verb-json-parse-json-stringify/0012/expout
+++ b/test/cases/verb-json-parse-json-stringify/0012/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "\"localhost\"",
   "pid": "12345",
@@ -7,3 +8,4 @@
   "empty2": "[]",
   "wrapper": "{\"empty3\": {}, \"emtpy4\": []}"
 }
+]
diff --git a/test/cases/verb-json-parse-json-stringify/0013/expout b/test/cases/verb-json-parse-json-stringify/0013/expout
index 261a409ed..8c341fcb7 100644
--- a/test/cases/verb-json-parse-json-stringify/0013/expout
+++ b/test/cases/verb-json-parse-json-stringify/0013/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -16,3 +17,4 @@
     "emtpy4": []
   }
 }
+]
diff --git a/test/cases/verb-json-parse-json-stringify/0015/expout b/test/cases/verb-json-parse-json-stringify/0015/expout
index ee6ab25b8..3336298c7 100644
--- a/test/cases/verb-json-parse-json-stringify/0015/expout
+++ b/test/cases/verb-json-parse-json-stringify/0015/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -16,3 +17,4 @@
     "emtpy4": []
   }
 }
+]
diff --git a/test/cases/verb-json-parse-json-stringify/0016/expout b/test/cases/verb-json-parse-json-stringify/0016/expout
index 261a409ed..8c341fcb7 100644
--- a/test/cases/verb-json-parse-json-stringify/0016/expout
+++ b/test/cases/verb-json-parse-json-stringify/0016/expout
@@ -1,3 +1,4 @@
+[
 {
   "hostname": "localhost",
   "pid": 12345,
@@ -16,3 +17,4 @@
     "emtpy4": []
   }
 }
+]
diff --git a/test/cases/verb-regularize/0002/expout b/test/cases/verb-regularize/0002/expout
index 19e3b4959..dcdf75946 100644
--- a/test/cases/verb-regularize/0002/expout
+++ b/test/cases/verb-regularize/0002/expout
@@ -1,16 +1,18 @@
+[
 {
   "b": 2,
   "c": 3,
   "a": 1
-}
+},
 {
   "b": 2,
   "c": 3,
   "a": 1
-}
+},
 {
   "d": 4,
   "a": 1,
   "b": 2,
   "c": 3
 }
+]
diff --git a/test/cases/verb-reshape/0013/expout b/test/cases/verb-reshape/0013/expout
index f57b37829..984b75ae9 100644
--- a/test/cases/verb-reshape/0013/expout
+++ b/test/cases/verb-reshape/0013/expout
@@ -1,136 +1,137 @@
+[
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "item": "x",
   "value": 0.3467901443380824
-}
+},
 {
   "a": "pan",
   "b": "pan",
   "i": 1,
   "item": "y",
   "value": 0.7268028627434533
-}
+},
 {
   "a": "eks",
   "b": "pan",
   "i": 2,
   "item": "x",
   "value": 0.7586799647899636
-}
+},
 {
   "a": "eks",
   "b": "pan",
   "i": 2,
   "item": "y",
   "value": 0.5221511083334797
-}
+},
 {
   "a": "wye",
   "b": "wye",
   "i": 3,
   "item": "x",
   "value": 0.20460330576630303
-}
+},
 {
   "a": "wye",
   "b": "wye",
   "i": 3,
   "item": "y",
   "value": 0.33831852551664776
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "i": 4,
   "item": "x",
   "value": 0.38139939387114097
-}
+},
 {
   "a": "eks",
   "b": "wye",
   "i": 4,
   "item": "y",
   "value": 0.13418874328430463
-}
+},
 {
   "a": "wye",
   "b": "pan",
   "i": 5,
   "item": "x",
   "value": 0.5732889198020006
-}
+},
 {
   "a": "wye",
   "b": "pan",
   "i": 5,
   "item": "y",
   "value": 0.8636244699032729
-}
+},
 {
   "a": "zee",
   "b": "pan",
   "i": 6,
   "item": "x",
   "value": 0.5271261600918548
-}
+},
 {
   "a": "zee",
   "b": "pan",
   "i": 6,
   "item": "y",
   "value": 0.49322128674835697
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "i": 7,
   "item": "x",
   "value": 0.6117840605678454
-}
+},
 {
   "a": "eks",
   "b": "zee",
   "i": 7,
   "item": "y",
   "value": 0.1878849191181694
-}
+},
 {
   "a": "zee",
   "b": "wye",
   "i": 8,
   "item": "x",
   "value": 0.5985540091064224
-}
+},
 {
   "a": "zee",
   "b": "wye",
   "i": 8,
   "item": "y",
   "value": 0.976181385699006
-}
+},
 {
   "a": "hat",
   "b": "wye",
   "i": 9,
   "item": "x",
   "value": 0.03144187646093577
-}
+},
 {
   "a": "hat",
   "b": "wye",
   "i": 9,
   "item": "y",
   "value": 0.7495507603507059
-}
+},
 {
   "a": "pan",
   "b": "wye",
   "i": 10,
   "item": "x",
   "value": 0.5026260055412137
-}
+},
 {
   "a": "pan",
   "b": "wye",
@@ -138,3 +139,4 @@
   "item": "y",
   "value": 0.9526183602969864
 }
+]
diff --git a/test/cases/verb-sort-within-records/0002/expout b/test/cases/verb-sort-within-records/0002/expout
index 7a56a44ef..d574f0688 100644
--- a/test/cases/verb-sort-within-records/0002/expout
+++ b/test/cases/verb-sort-within-records/0002/expout
@@ -1,13 +1,15 @@
+[
 {
   "a": 1,
   "b": 2
-}
+},
 {
   "a": 1,
   "b": 2
-}
+},
 {
   "a": 1,
   "b": 2,
   "c": 3
 }
+]
diff --git a/test/cases/verb-sort-within-records/0003/expout b/test/cases/verb-sort-within-records/0003/expout
index 7a56a44ef..d574f0688 100644
--- a/test/cases/verb-sort-within-records/0003/expout
+++ b/test/cases/verb-sort-within-records/0003/expout
@@ -1,13 +1,15 @@
+[
 {
   "a": 1,
   "b": 2
-}
+},
 {
   "a": 1,
   "b": 2
-}
+},
 {
   "a": 1,
   "b": 2,
   "c": 3
 }
+]
diff --git a/todo.txt b/todo.txt
index d2e7a5192..5caaee4d4 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,6 +1,23 @@
 ================================================================
 PUNCHDOWN LIST
 
+----------------------------------------------------------------
+JSON LINES
+k on input each will accept the other; key is on output
+k mark as legacy: --jlistwrap and --jvstack
+k olh
+k --l2X and --X2l -- ?
+k docs:
+  k 10min
+  k file-formats (obv)
+    https://jsonlines.org/
+  k glossary
+  k jlistwrap/jvstack grep
+  k nim6
+* RT cases
+
+----------------------------------------------------------------
+
 * compat emph
 * document cloudthings, e.g.
   o go.yml
@@ -10,6 +27,7 @@ PUNCHDOWN LIST
 * ngrams.sh -v -o 1 one-word-list.txt
 * sync-print option; or (yuck) another xprint variant; or ...; emph dump/eprint
 ? trace-mode ?
+* double-check utf8 / ngram splicing
 
 * doc
   o new-in-miller-6: missing:
@@ -46,6 +64,8 @@ PUNCHDOWN LIST
 ================================================================
 NON-BLOCKERS
 
+* contact re https://jsonlines.org/on_the_web/
+
 * Better functions for values manipulation, e.g. easier conversion of strings like "$1,234.56" into numeric values
 
 * IP addresses and ranges as a datatype so one could do membership tests like "if 10.10.10.10 in 10.0.0.0/8".