From c856ee865968736c1aff71676a59c246a8673537 Mon Sep 17 00:00:00 2001 From: Andrew Collier Date: Sat, 29 Oct 2022 16:36:19 +0100 Subject: [PATCH 1/3] feat: Add pre-commit hooks --- .pre-commit-config.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..fd16ba2 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,10 @@ +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v3.2.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - id: check-added-large-files From 3ddccb1f22fdca4d3ec4d8a4ccb3687d4137b2c5 Mon Sep 17 00:00:00 2001 From: Andrew Collier Date: Sat, 29 Oct 2022 16:45:05 +0100 Subject: [PATCH 2/3] chore: Trim trailing whitespace --- Class usage primer.md | 12 +- README.md | 96 ++--- User Guide.md | 928 +++++++++++++++++++++--------------------- Walk-path tutorial.md | 270 ++++++------ jtc.cpp | 2 +- lib/Json.hpp | 4 +- lib/Outable.hpp | 2 +- lib/extensions.hpp | 8 +- 8 files changed, 661 insertions(+), 661 deletions(-) diff --git a/Class usage primer.md b/Class usage primer.md index 26f6c0b..e130865 100644 --- a/Class usage primer.md +++ b/Class usage primer.md @@ -16,10 +16,10 @@ Below is the code sample how that could be achieved using `Json.hpp` class and t using namespace std; -int main(int argc, char *argv[]) { +int main(int argc, char *argv[]) { // read and parse json from cin: Json jin{ {istream_iterator{cin>>noskipws}, istream_iterator{}} }; - + // get all the names into vector and sort them vector names{jin.walk("l:"), jin.walk().end()}; sort(names.begin(), names.end()); @@ -29,8 +29,8 @@ int main(int argc, char *argv[]) { for(const auto &name: names) sorted.push_back(move( *jin.walk("[Name]:<" + name + ">[-1]") )); - // // put back into the original container and print using indentation 3 - jin["AddressBook"].clear().push_back( move(sorted) ); + // // put back into the original container and print using indentation 3 + jin["AddressBook"].clear().push_back( move(sorted) ); cout << jin.tab(3) << endl; } ``` @@ -38,7 +38,7 @@ int main(int argc, char *argv[]) { **Output result:** ```bash bash $ c++ -o sort_ab -Wall -std=c++14 sorting_ab.cpp -bash $ +bash $ bash $ ` or `>..<` (for a recursive and non-recursive searches respectively); search lexemes facilitate various match criteria defined by an optional suffix and/or quantifier >There's also a 3rd kind of lexemes - **_directives_**: they typically facilitate other functions like working with _namespaces_, -controlling walk-path execution, etc; _directives_ are syntactically similar to the _search lexemes_ +controlling walk-path execution, etc; _directives_ are syntactically similar to the _search lexemes_ All lexemes can be _iterable_: - - iterable **_subscripts_** let iterating over children of currently addressed JSON iterables nodes (arrays/objects), + - iterable **_subscripts_** let iterating over children of currently addressed JSON iterables nodes (arrays/objects), - while iterable **_search lexemes_** let iterating over all (recursive) matches for a given search criteria A _walk-path_ may have an arbitrary number of lexemes -the tool accepts a virtually unlimited number of walk @@ -77,14 +77,14 @@ For compiling, **`c++14`** (or later) is required. To compile under different pl - **Linux**: - non-relocatable (_dynamically_ linked) image: - `c++ -o jtc -Wall -std=gnu++14 -Ofast -pthread -lpthread jtc.cpp` - - relocatable (_statically_ linked) image: + - relocatable (_statically_ linked) image: - `c++ -o jtc -Wall -std=gnu++14 -Ofast -static -Wl,--whole-archive -lrt -pthread -lpthread -Wl,--no-whole-archive jtc.cpp` - **Debian**: - `c++ -o jtc -Wall -std=c++14 -pthread -lpthread -Ofast jtc.cpp` (ensure `c++` poits to `clang++-6.0` or above) Following debug related flags could be passed to `jtc` when compiling: - `-DNDEBUG`: compile w/o debugs, however it's unadvisable - there's no performance gain from doing so -- `-DNDBG_PARSER`: disable debugs coming from parsing JSON (handy when deep debugging huge JSONs and want to skip parsing debugs) +- `-DNDBG_PARSER`: disable debugs coming from parsing JSON (handy when deep debugging huge JSONs and want to skip parsing debugs) - `-DBG_FLOW`: all debuggable function/method calls will disply an entry and exit points - `-DBG_mTS`, `-DBG_uTS`: display absolute time-stamps in the debug: with millisecond accuracy and with microsecond accuracy respectively - `-DBG_dTS`: used with either of 2 previous flags: makes time-stamp to display delta (since last debug message) instead of absolute stamp @@ -92,7 +92,7 @@ Following debug related flags could be passed to `jtc` when compiling: #### Linux and MacOS precompiled binaries are available for download Choose the latest **precompiled binary**: -- _latest_ [macOS](https://github.com/ldn-softdev/jtc/releases/download/LatestBuild/jtc-macos-64.latest) +- _latest_ [macOS](https://github.com/ldn-softdev/jtc/releases/download/LatestBuild/jtc-macos-64.latest) >if you don't want to go through _macOS_ security hurdle, then remove the _quarantine_ attribute from the file >after binary download, e.g. (assuming you opened terminal in the folder where downloaded binary is): >``` @@ -202,7 +202,7 @@ bash $ jtc -w'l:' Bookmarks "https://en.cppreference.com/" ``` Let's take a look at the walk-path **`l:`**: -- search lexemes are enclosed in angular brackets `<`, `>` - that style provides a **recursive search** throughout JSON +- search lexemes are enclosed in angular brackets `<`, `>` - that style provides a **recursive search** throughout JSON - suffix **`l`** instructs to search among **labels** only - quantifier **`:`** instructs to find **all occurrences**, such quantifiers makes a path *iterable* @@ -215,11 +215,11 @@ bash $ jtc -w'[-1][children][:][name]' Bookmarks ``` Here the walk-path **`[-1][children][:][name]`** is made of following lexemes: -a. **``**: find within a JSON tree the **first** occurrence where the **JSON string** value is matching **`"Work"`** exactly -b. **`[-1]`**: **step up** one tier in the JSON tree structure (i.e., address an immediate parent of the found JSON element) -c. **`[children]`**: **select/address** a node whose label is **`"children"`** (it'll be a JSON array, at the same tier with `Work`) -d. **`[:]`**: select **each node** in the array -e. **`[name]`**: select/address a node with the label **`"name"`** +a. **``**: find within a JSON tree the **first** occurrence where the **JSON string** value is matching **`"Work"`** exactly +b. **`[-1]`**: **step up** one tier in the JSON tree structure (i.e., address an immediate parent of the found JSON element) +c. **`[children]`**: **select/address** a node whose label is **`"children"`** (it'll be a JSON array, at the same tier with `Work`) +d. **`[:]`**: select **each node** in the array +e. **`[name]`**: select/address a node with the label **`"name"`** in order to understand better how the walk-path works, let's run that series of cli in a slow-motion, gradually adding lexemes @@ -285,7 +285,7 @@ bash $ jtc -w'[-1][children][:][name]' -l Bookmarks "name": "Stack Overflow" "name": "C++ reference" ``` -> B.t.w., a better (a bit faster and more efficient) walk-path achieving the same query would be this: +> B.t.w., a better (a bit faster and more efficient) walk-path achieving the same query would be this: > - `jtc -w'[-1][children]l:' Bookmarks` #### 3. dump all URL's names: @@ -341,7 +341,7 @@ bash $ jtc -w'l:' -w'l:[-1][name]' -jl Bookmarks Enabling too many debugs might be overwhelming, though one specific case many would find extremely useful - when validating a failing JSON: ```bash -bash $ | (offset: 967) jtc json parsing exception (:967): expected_json_value -bash $ +bash $ ``` ## Complete User Guide there's a lot more under the hood of `jtc`: -- various viewing options, +- various viewing options, - directives allowing controlling walks, preserving parts of whole JSONs in namespaces, walking with various criteria, etc - interpolating namespaces and walk results in templates and lexemes - amending input JSONs via purge/swap/update/insert/move/merge operations @@ -373,7 +373,7 @@ Refer to a [Class usage primer](https://github.com/ldn-softdev/jtc/blob/master/C ## `jtc` vs **jq**: -`jtc` was _inspired_ by the complexity of **jq** interface (and its +`jtc` was _inspired_ by the complexity of **jq** interface (and its [DSL](https://en.wikipedia.org/wiki/Domain-specific_language)), aiming to provide users a tool which would let attaining the desired JSON queries in an easier, more feasible and succinct way @@ -385,22 +385,22 @@ aiming to provide users a tool which would let attaining the desired JSON querie using `/` delimiter **jq** is non-idiomatic in a _unix way_, e.g.: one can write a program in **jq** language that even has nothing to do with JSON. -Most of the requests (if not all) to manipulate JSONs are _ad hoc_ type of tasks, and learning **jq**'s DSL for _ad hoc_ type of tasks +Most of the requests (if not all) to manipulate JSONs are _ad hoc_ type of tasks, and learning **jq**'s DSL for _ad hoc_ type of tasks is an overkill (that purpose is best facilitated with -[GPL](https://en.wikipedia.org/wiki/General-purpose_language), e.g.: _Python_). +[GPL](https://en.wikipedia.org/wiki/General-purpose_language), e.g.: _Python_). The number of asks on the -[stackoverflow](https://stackoverflow.com/) -to facilitate even simple queries for **jq** is huge - that's the proof in itself that for many people feasibility of attaining their +[stackoverflow](https://stackoverflow.com/) +to facilitate even simple queries for **jq** is huge - that's the proof in itself that for many people feasibility of attaining their asks with **jq** is a way too low, hence they default to posting their questions on the forum. `jtc` on the other hand is a utility (not a language), which employs a novel but powerful concept, which "embeds" the ask right into the -_walk-path_. That facilitates a much higher feasibility of attaining a desired result: building a walk-path a lexeme by lexeme, +_walk-path_. That facilitates a much higher feasibility of attaining a desired result: building a walk-path a lexeme by lexeme, one at a time, provides an immediate visual feedback and let coming up with the desired result rather quickly. #### learning curve: - - **jq**: before you could come up with a query to handle even a relatively simple ask, you need to become an expert in - **jq** language, which will take some time. Coming up with the complex queries requires what it seems having a PhD in **jq**, or spending + - **jq**: before you could come up with a query to handle even a relatively simple ask, you need to become an expert in + **jq** language, which will take some time. Coming up with the complex queries requires what it seems having a PhD in **jq**, or spending lots of time on stackoverflow and similar forums - `jtc` employs only a simple (but powerful) concept of the _walk-path_ (which is made only of 2 types of search lexemes, each type though has several variants) which is quite easy to grasp. @@ -410,14 +410,14 @@ one at a time, provides an immediate visual feedback and let coming up with the - **jq**: handling irregular JSONs for **jq** is not a challenge, building a query is! The more irregularities you need to handle the more challenging the query (**jq** program) becomes - `jtc` was conceived with the idea of being capable of handling complex irregular JSONs with a simplified interface - that all is - fitted into the concept of the _walk-path_, while daisy-chaining multiple operations is possible to satisfy almost every ask. + fitted into the concept of the _walk-path_, while daisy-chaining multiple operations is possible to satisfy almost every ask. #### solutions input invariance \- most of `jtc` solutions would be input invariant (hardly the same could be stated for **jq**). Not that it's impossible to come up with invariant solutions in **jq**, it's just a lot more harder, while `jtc` with its walk-path model prompts for invariant solutions. -I.e., the invariant solution will keep working even once the JSON outer format changes (the invariant solution only would stop working -once the relationship between walked JSON elements changes). +I.e., the invariant solution will keep working even once the JSON outer format changes (the invariant solution only would stop working +once the relationship between walked JSON elements changes). E.g.: consider a following query, extract format `[ "name", "surname" ]` from 2 types of JSON: ```bash bash $ case1='{"Name":"Patrick", "Surname":"Lynch", "gender":"male", "age":29}' @@ -439,12 +439,12 @@ bash $ <<<$case2 jq -c 'if type == "array" then .[] else . end | [.Name, .Surnam ["Patrick","Lynch"] ["Alice","Price"] ``` -The both solutions work correctly, however, any change in the outer encapsulation will break **jq**'s solution , +The both solutions work correctly, however, any change in the outer encapsulation will break **jq**'s solution , while `jtc` will keep working even if JSON is reshaped into an _irregular_ structure, e.g.: ```bash #jtc: bash $ case3='{"root":[{"Name":"Patrick", "Surname":"Lynch", "gender":"male", "age":29}, {"closed circle":[{"Name":"Alice", "Surname":"Price", "gender":"female", "age":27}, {"Name":"Rebecca", "Surname":"Hernandez", "gender":"female", "age":28}]}]}' -bash $ +bash $ bash $ <<<$case3 jtc -w'l:[-1]' -rT'[{{$a}},{{$b}}]' [ "Patrick", "Lynch" ] [ "Alice", "Price" ] @@ -454,12 +454,12 @@ bash $ <<<$case3 jtc -w'l:[-1]' -rT'[{{$a}},{{$b}}]' bash $ <<<$case3 jq -c 'if type == "array" then .[] else . end | [.Name, .Surname]' [null,null] ``` -The same property makes `jtc` solutions resistant to cases of incomplete data, e.g.: if we drop `"Name"` entry from one of the +The same property makes `jtc` solutions resistant to cases of incomplete data, e.g.: if we drop `"Name"` entry from one of the entries in case 2, `jtc` solution still works correctly: ```bash #jtc: bash $ case2='[{"Surname":"Lynch", "gender":"male", "age":29},{"Name":"Alice", "Surname":"Price", "gender":"female", "age":27}]' -bash $ +bash $ bash $ <<<$case2 jtc -w'l:[-1]' -rT'[{{$a}},{{$b}}]' [ "Alice", "Price" ] @@ -468,7 +468,7 @@ bash $ <<<$case2 jq -c 'if type == "array" then .[] else . end | [.Name, .Surnam [null,"Lynch"] ["Alice","Price"] ``` -\- i.e., `jtc` will not assume that user would require some default substitution in case of incomplete data (but if such handling is +\- i.e., `jtc` will not assume that user would require some default substitution in case of incomplete data (but if such handling is required then the walk-path can be easily enhanced) @@ -477,13 +477,13 @@ required then the walk-path can be easily enhanced) ([here's what I mean](https://github.com/ldn-softdev/cpluspus-vs-c)) - `jtc` is written in the idiomatic _C++14_ using STL only. `jtc` does not have a single naked memory allocation operator (those few `new` operators required for legacy interface are implemented as _guards_), - nor it has a single naked pointer acting as a resource holder/owner, thus `jtc` is guaranteed to be **free of memory/resources leaks** - (at least one class of the problems is off the table) - **STL guaranty**. + nor it has a single naked pointer acting as a resource holder/owner, thus `jtc` is guaranteed to be **free of memory/resources leaks** + (at least one class of the problems is off the table) - **STL guaranty**. Also, `jtc` is written in a very portable way, it should not cause problems compiling it under any unix like system. #### JSON numerical fidelity: - - **jq** is not compliant with JSON numerical definition. What jq does, it simply converts a symbolic numerical representation to an + - **jq** is not compliant with JSON numerical definition. What jq does, it simply converts a symbolic numerical representation to an internal binary and keeps it that way. That approach: - is not compliant with JSON definition of the numerical values - it has problems retaining required precision @@ -491,8 +491,8 @@ required then the walk-path can be easily enhanced) - leads to incorrect processing of some JSON streams - `jtc` validates all JSON numericals per JSON standard and keep numbers internally in their original literal format, so it's free of all the above caveats, compare: - - Handling | `jtc` | **jq 1.6** + + Handling | `jtc` | **jq 1.6** --- | ---: | :--- Invalid Json: `[00]` | `<<<'[00]' jtc` | `<<<'[00]' jq -c .` _Parsing result_ | `jtc json parsing exception (:3): missed_prior_enumeration` | `[0]` @@ -509,10 +509,10 @@ _Parsing result_ | `[ {}, [], "bar", "foo", 0, 0, 123, true, false, null ]` | `p - `jtc` engages a _concurrent_ (multi-threaded) reading/parsing when multiple files given (the advantage could be observed on multi-core CPU, though it become noticeable only with relatively big JSONs or with relatively big number of files processed) -**_Comparison of single-threaded performance:_** +**_Comparison of single-threaded performance:_** Here's a 4+ million node JSON file [standard.json](https://github.com/ldn-softdev/jtc/releases/download/standard.json/standard.json): ``` -bash $ time jtc -zz standard.json +bash $ time jtc -zz standard.json 4329975 user 6.085 sec ``` @@ -537,23 +537,23 @@ _**`updating JSON recursively by label:`**_ | _**`updating JSON recursively by l **_Comparison of `jtc` to `jtc` (single-threaded to multi-threaded parsing performance):_** ```bash bash $ unset TIMEFORMAT -bash $ +bash $ bash $ # concurrent (multi-threaded) parsing: -bash $ time jtc -J / -zz standard.json standard.json standard.json standard.json standard.json +bash $ time jtc -J / -zz standard.json standard.json standard.json standard.json standard.json 21649876 real 0m10.995s # <- compare these figures user 0m34.083s sys 0m3.288s -bash $ +bash $ bash $ # sequential (single-threaded) parsing: -bash $ time jtc -aJ / -zz standard.json standard.json standard.json standard.json standard.json +bash $ time jtc -aJ / -zz standard.json standard.json standard.json standard.json standard.json 21649876 real 0m31.717s # <- compare these figures user 0m30.125s sys 0m1.555s -bash $ +bash $ ``` @@ -573,7 +573,7 @@ Machine spec used for testing: ### compare `jtc` based solutions with *jq*'s: [Here](https://github.com/ldn-softdev/stackoverflow-json/blob/master/README.md) -are published some answers for JSON queries using `jtc`, you may compare those with `jq`'s, as well as study the +are published some answers for JSON queries using `jtc`, you may compare those with `jq`'s, as well as study the feasibility of the solutions, test relevant performance, etc diff --git a/User Guide.md b/User Guide.md index 915886c..58b445e 100644 --- a/User Guide.md +++ b/User Guide.md @@ -3,7 +3,7 @@ 1. [Displaying JSON](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#displaying-json) * [Pretty printing (`-t`)](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#pretty-printing) * [Compact printing (`-r`)](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#compact-printing) - * [Semi-compact printing (`-tNc`,`-tc`)](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#semi-compact-printing) + * [Semi-compact printing (`-tNc`,`-tc`)](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#semi-compact-printing) * [Printing JSON size (`-z`, `-zz`)](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#printing-json-size) * [Validating JSON (`-d`)](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#validating-json) * [Forcing strict solidus parsing (`-q`)](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#forcing-strict-solidus-parsing) @@ -61,8 +61,8 @@ * [Templates (`-T`)](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#templates) * [Multiple templates and walks](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#multiple-templates-and-walks) * [Stringifying JSON, Jsonizing stringified(`>{{}}<`, `>>{{}}<<`, `<{{}}>`, `<<{{}}>>`)](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#stringifying-json-jsonizing-stringified) - * [Summary of interpolation token types](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#summary-of-interpolation-token-types) - * [Summary of namespace tokens](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#summary-of-namespace-tokens) + * [Summary of interpolation token types](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#summary-of-interpolation-token-types) + * [Summary of namespace tokens](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#summary-of-namespace-tokens) 4. [Modifying JSON](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#modifying-json) * [In-place JSON modification (`-f`)](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#in-place-json-modification) * [Forcing input read from `stdin` (`-`)](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#forcing-input-read-from-stdin) @@ -113,7 +113,7 @@ ## Displaying JSON ### Pretty printing -If no argument given, `jtc` will expect an input JSON from the ``, otherwise JSON is read from the file(s) pointed by the +If no argument given, `jtc` will expect an input JSON from the ``, otherwise JSON is read from the file(s) pointed by the argument(s). `jtc` will parse and validate input JSON and upon a successful validation will output: ```bash bash $ :1214): unexpected_end_of_line -bash $ +bash $ ``` and though the message lets us knowing that there's a problem with the input JSON, it not very informative with regards whereabouts the the problem. To visualize the spot where the problem is, as well as its locus pass a single debug option (`-d`): @@ -312,9 +312,9 @@ bash $ | (offset: 1214) jtc json parsing exception (:1214): unexpected_end_of_line -bash $ +bash $ ``` -the vertical pipe symbol `|` in the debug showing JSON locus replaces new lines, thus it becomes easy to spot the problem. +the vertical pipe symbol `|` in the debug showing JSON locus replaces new lines, thus it becomes easy to spot the problem. The offset (`1214` in the example) is given in _unicode UTF-8_ characters from the beginning of the input/file/stream. In that particular failure instance, `jtc` found the end of a line, while _JSON string_ `"Co,` is still open (JSON standard does not permit multi-line strings). To fix that, the missing quotation mark to be added @@ -328,7 +328,7 @@ bash $ <<<'{ "escaped": "\/", "unescaped": "/" }' jtc "escaped": "/", "unescaped": "/" } -bash $ +bash $ ``` If there's a need for a strict solidus parsing, option `-q` facilitates the need. It also will throw an exception upon facing a non-escaped notation: @@ -339,7 +339,7 @@ bash $ <<<'{ "escaped": "\/", "unescaped": "/" }' jtc -q -d .exception_locus_(), { "escaped": "\/", "unescaped": "/" } .exception_spot_(), --------------------------------->| (offset: 33) jtc json parsing exception (:33): unquoted_character -bash $ +bash $ ``` ### Unquoting JSON strings @@ -347,13 +347,13 @@ If a JSON itself (or a result from walking JSON) is a single JSON string, then s (especially it comes handy if the string itself is an embedded JSON). `-qq` allows unquoting it, here are a few examples: ```bash bash $ jsn='"{ \"JSON\": \"example of an embedded JSON\" }"' -bash $ <<<$jsn jtc +bash $ <<<$jsn jtc "{ \"JSON\": \"example of an embedded JSON\" }" -bash $ +bash $ # unquote (jsonize) embedded json: bash $ <<<$jsn jtc -qq { "JSON": "example of an embedded JSON" } -bash $ +bash $ # unquote (jsonize) embedded json and re-parse it: bash $ <<<$jsn jtc -qq | jtc { @@ -367,7 +367,7 @@ When unquoting empty _JSON strings_ (`""`) the resulted blank lines are not even bash $ <<<'[null, "", true]' jtc -w[:] -qq null true -bash $ +bash $ ``` If the source string contains Unicode code points, those will be correctly translated into @@ -375,18 +375,18 @@ respective UTF-8 characters: ```bash bash $ <<<'"Unicode char: \u1234"' jtc -qq Unicode char: ሴ -bash $ +bash $ bash $ <<<'"Surrogate pair: \uD834\uDD1E"' jtc -qq Surrogate pair: 𝄞 -bash $ +bash $ bash $ <<<'"Invalid surrogate: \uDD1E"' jtc -qq jtc json exception: invalid_surrogate_code_pair -bash $ +bash $ ``` > NOTE: _the option notation `-qq` will not engulf a single option notation `-q`, if both behaviors are required then both variants have -to be spelled (e.g. `jtc -q -qq`, or `jtc -qqq`)_ +to be spelled (e.g. `jtc -q -qq`, or `jtc -qqq`)_ > Also, `-qq` is incompatible with `-j`, `-J` options, because of a risk of forming an ill-formed JSON, thus, when sighted together option `-qq` is silently ignored @@ -411,10 +411,10 @@ The spacer for stringification is also controlled via `-t`, e.g.: to stringify t ```bash bash $ <<<$jsn jtc -rr -t0 "[\"JSON\",\"example\"]" -bash $ +bash $ ``` -> B.t.w., both _string unquoting_ and _JSON stringification_ also could be achieved via +> B.t.w., both _string unquoting_ and _JSON stringification_ also could be achieved via [template operations](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#stringifying-json-jsonizing-stringified). @@ -422,7 +422,7 @@ bash $ - [`-tN`](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#pretty-printing): pretty printing using indentation with N spaces (by default `N` is `3`) - [`-r`](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#compact-printing): -compact (single row) printing using with a default spacer (1 white space) +compact (single row) printing using with a default spacer (1 white space) - [`-rtN`](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#compact-printing): compact printing using `N` white spaces as a spacer - [`-tNc`](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#semi-compact-printing): @@ -496,7 +496,7 @@ There, all records (`[+0]`) from the `Directory` have been selected and then in starting from the 2nd entry (`[+1]`) The same way object elements could be subscripted, here's an example where all address entries starting from the 2nd one are printed, -each one stating from the 3rd entry: +each one stating from the 3rd entry: ```bash bash $ ` braces instruct to perform a _recursive_ search off the value under a currently selected JSON node. I.e., if a search lexeme appears as the first one in the walk-path, then the search will be performed off the root, otherwise off the node in JSON where a prior lexeme has stopped. - -By default (if no suffix is given), a search lexeme will perform a search among _JSON string_ values only (i.e., it won't match + +By default (if no suffix is given), a search lexeme will perform a search among _JSON string_ values only (i.e., it won't match _JSON numerical_ or _JSON boolean_ or _JSON null_ values). E.g., following search produces a match: ```bash bash $ ' "New York" bash $ ``` -while this one doesn't produce a match (the string value `"New York"` is found only in the first `Directory` record): +while this one doesn't produce a match (the string value `"New York"` is found only in the first `Directory` record): ```bash bash $ ' bash $ @@ -555,7 +555,7 @@ bash $ #### Searching JSON with RE Optionally, search lexemes may accept _one-letter suffixes_: a single character following the lexeme's closing bracket. -The suffixes define lexeme's search behavior. +The suffixes define lexeme's search behavior. For example, these 3 suffixes facilitate _REGEX_ types of search: - `R`: performs a _REGEX search_ only among JSON _string_ values - `D`: performs a _REGEX search_ only among JSON _numerical_ values @@ -570,7 +570,7 @@ bash $ REGEX lexemes optionally may have flags altering RE search behavior ([cppreference](https://en.cppreference.com/w/cpp/regex/syntax_option_type)): -- `I` (icase): - character matching should be performed without regard to case +- `I` (icase): - character matching should be performed without regard to case - `N` (nosubs): - sub-expressions `(expr)` are treated as non-marking sub-expressions `(?:expr)` - `O` (optimize): - make matching faster, with the potential cost of making construction slower - `C` (collate): - character ranges of the form "[a-b]" will be locale sensitive @@ -588,32 +588,32 @@ All of the above flags may be passed as _quoted trailing characters_ in the lexe ```bash bash $ R' "New York" -bash $ +bash $ ``` -> Multiple options could be passed within the lexeme, however, if multiple grammars specified, only the first one will take the effect, +> Multiple options could be passed within the lexeme, however, if multiple grammars specified, only the first one will take the effect, e.g.: `<...\G\A>R` - between `awk` and `grep` grammars the latter wins, because it's given first -All REGEX lexemes also support templates/namespace +All REGEX lexemes also support templates/namespace [interpolation](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#interpolation). The ineterpolation is applied before regex search performed: ```bash bash $ l:v[-1][street address]<[{PC}]>R' "5423 Madison St" "6213 E Colfax Ave" -bash $ +bash $ ``` \- in the last lexeme (`<[{PC}]>R`) the namespace `PC` is getting interpolated first (it was set in the second lexeme - `v`) and then the REGEX search applied. ->_NOTE: the namespace tokens usage in REGEX lexemes is restricted to alphabetical names only (e.g.: `{abc}`): ->\- numerical namespaces (e.g., `{123}` ) might be clashing with REGEX quantifiers and hence not supported, +>_NOTE: the namespace tokens usage in REGEX lexemes is restricted to alphabetical names only (e.g.: `{abc}`): +>\- numerical namespaces (e.g., `{123}` ) might be clashing with REGEX quantifiers and hence not supported, >\- the auto-tokens (e.g.: '$abc') are also unsupported, because at the time of walking the iterator is yet unresolved_ **_Be extreamly careful with all search lexemes supporting interpolation (namely: `<..>R`, `<..>L`, `<..>D`, `<..>j`) - reckless interpolation may render walking quite slow_** #### Search suffixes -This is the complete list of suffixes that control _search_ behavior: +This is the complete list of suffixes that control _search_ behavior: * `r`: default (could be omitted), fully matches _JSON string_ values (e.g.: ``, `r`) * `R`: the lexeme is a search RE, only _JSON string_ values searched (e.g.: `<^N.*>R`) * `P`: matches _any_ string values, same like `<.*>R`, just faster (e.g.: `<>P`) @@ -628,19 +628,19 @@ This is the complete list of suffixes that control _search_ behavior: * `a`: matches any JSON atomic value, i.e., _strings_, _numerical_, _boolean_, _null_ (e.g.: `<>a`) * `o`: matches any JSON object `{..}` (e.g.: `<>o`) * `i`: matches any JSON array `[..]` (e.g.: `<>i`) - * `c`: matches any container type - either arrays or objects (e.g.: `<>c`) + * `c`: matches any container type - either arrays or objects (e.g.: `<>c`) * `e`: matches end-nodes only, which is either atomic values, or empty iterables `[]`, `{}` (e.g.: `<>e`) * `w`: matches any JSON value (wide range match): atomic values, objects, arrays (e.g. `<>w`) * `j`: matches a JSON value; the lexeme can be either a valid JSON (e.g.: `<[]>j` - finds an empty JSON array), or a [template](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#templates) - resulting in a valid JSON after + resulting in a valid JSON after [interpolation](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#interpolation) (e.g.: `<"{str}">j` - finds a _JSON string_ whose value is in [namespace](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#namespace) `str`) * `s`: matches a JSON value previously stored in the namespace (e.g.: `v ... s`) - * `t`: matches a tag (label/index) previously stored in the namespace (e.g. `k ... t`) - * `q`: matches only original JSON values, i.e. selects non-duplicated values only (e.g.: `<>q`) + * `t`: matches a tag (label/index) previously stored in the namespace (e.g. `k ... t`) + * `q`: matches only original JSON values, i.e. selects non-duplicated values only (e.g.: `<>q`) * `Q`: matches only repetitive (duplicating) JSON values (e.g.: `<>Q`) * `g`: matches all JSON values in the ascending order (e.g.: `<>g`) * `G`: matches all JSON values in the descending order (e.g.: `<>G`) @@ -648,17 +648,17 @@ This is the complete list of suffixes that control _search_ behavior: Some search lexemes (and [directives](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#directives)) -require their content is set and be **non-empty** (`R`,`d`,`D`,`L`,`j`,`s`,`t`,`v`,`z`,`u`,`I`,`Z`,`W`,`S`), otherwise an exception +require their content is set and be **non-empty** (`R`,`d`,`D`,`L`,`j`,`s`,`t`,`v`,`z`,`u`,`I`,`Z`,`W`,`S`), otherwise an exception (_`walk_empty_lexeme`_) will be thrown, e.g.: ```bash bash $ L' "John" bash $ L' jtc json exception: walk_empty_lexeme -bash $ +bash $ ``` -The walk-path might be quite long containing multiple lexemes and it might not be obvious which one throws the exception. +The walk-path might be quite long containing multiple lexemes and it might not be obvious which one throws the exception. To figure that, run the command with `-ddd` - the throwing lexeme will be displayed: ```bash bash $ L' -ddd @@ -679,46 +679,46 @@ bash $ L' -ddd ...parse_suffix_(), search type sfx: Label_RE_search ..main(), exception raised by: file: './lib/Json.hpp', func: 'parse_suffix_()', line: 3573 jtc json exception: walk_empty_lexeme -bash $ +bash $ ``` A few of search lexemes might be left empty, but then they cary a semantic of an **empty match** (`r`,`l`): - `<>r` (same as `<>`) - will match an empty _JSON string_ - - `<>l` - will match an entry with the empty _JSON label_ + - `<>l` - will match an entry with the empty _JSON label_ E.g.: ```bash bash $ <<<'{"":"empty label"}' jtc -w'<>l' "empty label" -bash $ +bash $ ``` The rest of the lexemes (search: `P`,`N`,`b`,`n`,`a`,`o`,`i`,`c`,`e`,`w`,`q`,`Q`,`g`,`G` and directives: `k`,`f`,`F`) also might be left empty - all those search lexemes carry semantic of **any match**. However, if those lexemes are non-empty, then their content points to a [_namespace_](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#namespace) -where the found value (result of a match - for search lexemes, or currently walked JSON - for directives) will be stored, e.g.: +where the found value (result of a match - for search lexemes, or currently walked JSON - for directives) will be stored, e.g.: ```bash bash $ i1' -T'[{array}, "Sophia"]' [ "Olivia", "Sophia" ] -bash $ +bash $ bash $ i1' -T'[{array}, "Sophia"]' [ "Mia", "Sophia" ] -bash $ +bash $ ``` ##### \* Cached Search `jtc` is super efficient searching recursively even huge JSONs structures - normally no exponential search decay will be observed (which is very typical for such kind of operations). The decay is avoided because `jtc` builds a cache for **_all_** searches (whenever -cacheing is required, both recursive and non-recursive) and thus all subsequent matches are taken from the cache. +cacheing is required, both recursive and non-recursive) and thus all subsequent matches are taken from the cache. #### Directives @@ -727,7 +727,7 @@ for the currently walked JSON elements, these are _directives_: * `v`: saves the currently walked JSON value into a namespace under the name specified by the lexeme (e.g.: `v`) * `k`: instructs to reinterpret the key (label/index) of the currently walked JSON and treat it as a value (thus a label/index - can be updated/extracted programmatically) - e.g.: `<>k`; if the lexeme is non-empty then it saves a found key + can be updated/extracted programmatically) - e.g.: `<>k`; if the lexeme is non-empty then it saves a found key (label/index) into the corresponding namespace and **cancels reinterpretation** of the label as a value (e.g.: `k`) * `z`: erases namespace pointed by the lexeme's; the lexeme must not be empty (e.g.: `z`) * `f`: fail-safe (branching): if walking **past the fail-safe** lexeme fails then, instead of progressing to the next iteration @@ -741,11 +741,11 @@ for the currently walked JSON elements, these are _directives_: etc. * `>I3:2` - a JSON numerical stored in the namespace `val` will be incremented by 3 and then multiplied by 2. * `Z`: saved into a provided namespace a size of a currently walked JSON (recursive and non-recursive notations produces different effects - the former calculates the entire JSON size, while the latter does only the number of children); with the quantifier of `1` @@ -759,16 +759,16 @@ There's a set of lexemes (search and directives) which may reference a name in t [_namespace_](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#namespace) for capturing a currently walked JSON elements: `P`,`N`,`b`,`n`,`a`,`o`,`i`,`c`,`e`,`w`,`q`,`Q`,`g`,`G`,`v`,`k`,`f`,`F`. All of those lexemes also allow capturing a custom JSON value in lieu of currently walked JSON - if the lexeme's value is given in -the format, e.g.: -\- `v` +the format, e.g.: +\- `v` then upon walking such syntax the `JSON_value` will be preserved in the namespace `name` instead of a currently walked JSON -> Normally, `JSON_value` must be a valid JSON, otherwise it'll be promoted to a JSON string. If it still fails then an exception +> Normally, `JSON_value` must be a valid JSON, otherwise it'll be promoted to a JSON string. If it still fails then an exception will be thrown (`json_lexeme_invalid`) #### Fail-safe and Forward-Stop directives All the lexemes in the _walk-path_ are bound by a logical `AND` - only once all succeed then the walk-path succeeds too (and printed -or passed for a respective operation). The _fail-safe_ and _Forward-Stop_ directives make possible to introduce branching logic +or passed for a respective operation). The _fail-safe_ and _Forward-Stop_ directives make possible to introduce branching logic into the _walk-path_. Let's break it down: When directive `F` is paired with `<>f`, together they cover all cases of walk-paths branching: @@ -786,7 +786,7 @@ bash $ [-1]' -r "Ivan" { "number": "223-283-0372", "type": "mobile" } "Jane" -bash $ +bash $ ``` As it appears, `Jane` has no mobile phone, but then our requirement is enhanced: for those who do not have a `mobile`, let's list the first available phone from the records, there a `<>f` directive comes to a rescue: @@ -798,7 +798,7 @@ bash $ f [-1][-1]' -r { "number": "223-283-0372", "type": "mobile" } "Jane" { "number": "358-303-0373", "type": "office" } -bash $ +bash $ ``` as the path is walked, as soon `<>f` directive is faced, `jtc` _memorizes_ the currently walked path point and will _reinstate_ it shall further walking fails, there: @@ -807,13 +807,13 @@ further walking fails, there: * if it's found, we step back up (`[-1]`) again to finish walking and display the whole record * if not found (i.e., walking indeed fails), a fail-safe is engaged and preserved location is recalled and displayed -> A _walk-path_ may contain multiple _fail-safe_, only the respective fail-safe will be engaged (more specific one and closest +> A _walk-path_ may contain multiple _fail-safe_, only the respective fail-safe will be engaged (more specific one and closest one to the failing point) ##### \* Examples illustrating _fail-safe_ using namespaces and interpolation: -Say we want to list from the address book all the record holders and indicate whether they have any children or not in -this format: +Say we want to list from the address book all the record holders and indicate whether they have any children or not in +this format: ` has children: true/false` Thus, we need to build a single path, which will find the `name`, then inspect `children` record and transform it into @@ -822,11 +822,11 @@ Thus, we need to build a single path, which will find the `name`, then inspect ` We can do it in steps: 1. let's get to the `name`s first and memorize those: ```bash -bash $ l:v' +bash $ l:v' "John" "Ivan" "Jane" -bash $ +bash $ ``` 2. Now let's inspect a sibling record `children`: ```bash @@ -834,15 +834,15 @@ bash $ l:v [-1][children]' -r [ "Olivia" ] [] [ "Robert", "Lila" ] -bash $ +bash $ ``` 3. so far so good, now, we need to engage _fail-safe_ to facilitate the requirement to classify those records as `true` / `false`: ```bash -bash $ l:v[-1][children]f[0]v' +bash $ l:v[-1][children]f[0]v' "Olivia" [] "Robert" -bash $ +bash $ ``` - there namespace `C` will be populated first with JSON value `false` and will stay put shall further walking fails; - otherwise (i.e., upon a successful walk - addressing a first child `[0]`) the namespace `C` will be overwritten @@ -854,7 +854,7 @@ bash $ l:v[-1][children]f[0]v' -T'"{N} John has children: true Ivan has children: false Jane has children: true -bash $ +bash $ ``` ## Let's consider another example, say, we have a following JSON: @@ -867,7 +867,7 @@ bash $ <<<$jsn jtc -tc { "ip": "1.1.1.2", "name": "printer" }, { "ip": "1.1.1.101" } ] -bash $ +bash $ ``` How do we list only those records which **don't have** `name` and skip those which do? Well, one apparent solution then would be to walk all those entries, which do have `name` labels and purge them: @@ -877,7 +877,7 @@ bash $ <<<$jsn jtc -pw'l:[-1]' -tc { "ip": "1.1.1.100" }, { "ip": "1.1.1.101" } ] -bash $ +bash $ ``` But what if we want to walk entries rather than purge (e.g., for reason of template-interpolating the entries at the output)? The prior solution would require @@ -888,7 +888,7 @@ however, it's possible to achieve the same using this simple query: bash $ <<<$jsn jtc -w'[:]<>f[name]<>F' -tc { "ip": "1.1.1.100" } { "ip": "1.1.1.101" } -bash $ +bash $ ``` Without `<>F` directive at the end, the walk would look like this: ```bash @@ -897,27 +897,27 @@ bash $ <<<$jsn jtc -w'[:]<>f[name]' -tc { "ip": "1.1.1.100" } "printer" { "ip": "1.1.1.101" } -bash $ +bash $ ``` -Thus, `<>F` skips those (successfully) matched entries, leaving only ones which fail - that's what we need in this query +Thus, `<>F` skips those (successfully) matched entries, leaving only ones which fail - that's what we need in this query (the records which do not have `name` in it) -Now, what if in the example above (one with `<>F` directive) we want to process *failed* JSON further, say, to display `ip` only, +Now, what if in the example above (one with `<>F` directive) we want to process *failed* JSON further, say, to display `ip` only, rather than the whole record? That is easy - walking of the *failed* path continues past the `F` directive: ```bash bash $ <<<$jsn jtc -w'[:]<>f[name]<>F[ip]' -qq 1.1.1.100 1.1.1.101 -bash $ +bash $ ``` ##### \* Uses of `Fn` directive with non-default quantifiers there are couple other uses for `Fn` lexeme with a non-zero (non-default) quantifiers: - - `<>Fn` - that variant of the lexeme implements a **_jump_** logic for the walk path - i.e., once walked, it will jump to the `n`th + - `<>Fn` - that variant of the lexeme implements a **_jump_** logic for the walk path - i.e., once walked, it will jump to the `n`th lexeme (counting from the lexeme `<>F` itself) and continues walking from there. E.g.: `<>F1` does not do anything - it continues walking from the 1st lexeme after `<>F1`, - `<>F2` will jump over the very next lexeme and continues walking from the 2nd one, and so on and so forth. + `<>F2` will jump over the very next lexeme and continues walking from the 2nd one, and so on and so forth. - `>Fn`: bash $ l:<>f<>n<>F[-1][name]' "John" "Jane" -bash $ +bash $ # duplicate the same logic once: bash $ l:<>f<>n<>F[-1][name]>R:' bash $ R:' -T'"j{$1}"' "john" "jane" -bash $ +bash $ ``` -(coverage of REGEX is entirely out of scope of this document, rather refer to this external link: +(coverage of REGEX is entirely out of scope of this document, rather refer to this external link: [Regular Expression](https://www.regular-expressions.info/)) #### Search quantifiers -Optionally, a quantifier may follow the search lexeme (if a lexeme has a suffix, then the quantifier must come after the suffix). +Optionally, a quantifier may follow the search lexeme (if a lexeme has a suffix, then the quantifier must come after the suffix). Quantifiers in search lexemes allow selecting match instance (i.e., select first match, second one, etc, or a range of matches) Quantifiers exist in the following formats: - `n`, - a positive number - tells which instance of a match to pick. By default, a quantifier `0` is applied (i.e., first match selected) - `+n` - selects all match instances starting from `n`th (zero based) -- `n:m:s` - slice select: the notation rules for this quantifier the same as for +- `n:m:s` - slice select: the notation rules for this quantifier the same as for [subscript slices](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#subscript-slice-notation) (`[n:m:s]`), with just one understandable caveat: `n`,`m` here cannot go negative (there's no way of knowing upfront how many matches would be produced, so it's impossible to select a range/slice based off the last match), the rest of the notation rules apply @@ -992,9 +992,9 @@ bash $ _JSON arrays_ here - suffix `i`) starting from second one (all quantifiers and indices are zero-based) -##### \* Search quantifiers with relative offset semantic +##### \* Search quantifiers with relative offset semantic There are two search lexemes types where matching non-first instance does not make sense, namely: `>....bb........dR:' -l "street address": "6213 E Colfax Ave" "number": "358-303-0373" "number": "333-638-0238" -bash $ +bash $ ``` Some of the values are `street address`es, some are the phone `number`s. Say, we want to dump only the phone records using the same search criteria (lexeme). Knowing the label of the phone numbers (`"number"`), it's achievable via this notation: @@ -1056,17 +1056,17 @@ bash $ R:' -l "number": "223-283-0372" "number": "358-303-0373" "number": "333-638-0238" -bash $ +bash $ ``` -I.e., once the literal subscript lexeme is attached to the search lexeme over `:`, it makes a scoped search: +I.e., once the literal subscript lexeme is attached to the search lexeme over `:`, it makes a scoped search: (`[..]:<..>`). #### Non-recursive search Sometimes there's a requirement to apply a _non-recursive_ search onto iterable JSON nodes (arrays, objects) - i.e., find a value within immediate children of the node and do not descend recursively. The notation facilitating such search is the same one, but -angular brackets to be placed inside-out: `>..<`. -To illustrate that, say, we want to find all string values in the 1st `Directory` record containing the letter `o`. +angular brackets to be placed inside-out: `>..<`. +To illustrate that, say, we want to find all string values in the 1st `Directory` record containing the letter `o`. If we do this using a recursive search, then all following entries will be found: ```bash bash $ R:' @@ -1082,7 +1082,7 @@ bash $ o **One subtle but crucial difference between _recursive_ `<..>` and _non-recursive_ `>..<` searches: +> **One subtle but crucial difference between _recursive_ `<..>` and _non-recursive_ `>..<` searches: > \- the former starts a recursive search from a currently walked/selected element itself, i.e., if a currently selected JSON is `"pi"`, then this walk-path still matches: `` and so on. For the latter case the _non-recursive_ search performs matching strictly among currently walked JSON iterable's children** @@ -1116,7 +1116,7 @@ The magic which happens here (let's break down the walk-path into the lexemes): bash $ : [-1]' -tc { "number": "273-923-6483", "type": "home" } { "number": "333-638-0238", "type": "home" } - bash $ + bash $ # select 2nd parent: bash $ : [-2]' -tc @@ -1128,7 +1128,7 @@ The magic which happens here (let's break down the walk-path into the lexemes): { "number": "358-303-0373", "type": "office" }, { "number": "333-638-0238", "type": "home" } ] - bash $ + bash $ # select 3rd parent: bash $ : [-3]' -tc @@ -1154,7 +1154,7 @@ The magic which happens here (let's break down the walk-path into the lexemes): ], "spouse": "Chuck" } - bash $ + bash $ ``` 3. `[name]` - now we can select (subscript) `[name]` of out those selected JSON nodes ## @@ -1180,7 +1180,7 @@ bash $ The walk-path break down: 1. `l:` - find each record by label `"children"` 2. `[0]` - try addressing first element in the found records (that'll ensure that `children` is non-empty) -3. `[-2]` - go 2 parents up for those records which survived the prior step - that'll bring us to the person's record level +3. `[-2]` - go 2 parents up for those records which survived the prior step - that'll bring us to the person's record level 4. `[type]:` - find recursively `mobile` string scoped by `type` (already only for those records which have children) 5. `[-3]`- go 3 levels (parents) up (for those records which have `children` and have `mobile` types of phone records) - it'll bring us again up to the person's record level @@ -1198,10 +1198,10 @@ Note `[^2]` - this notation, likewise `[-n]` also selects a certain parent, howe (i.e., from the currently selected node) `[^n]` notation does it off the root. When `jtc` walks lexemes (traverse JSON tree), internally it maintains a path to the walked steps (it's visible via debugs `-dddd`). -E.g., when the first lexeme's match found (for `l:`), the internal walked steps path would look like: - `root -> [Directory] -> [0] -> [children]`, -then when the next lexeme is successfully applied, the internal path becomes: - `root -> [Directory] -> [0] -> [children] -> [0]` +E.g., when the first lexeme's match found (for `l:`), the internal walked steps path would look like: + `root -> [Directory] -> [0] -> [children]`, +then when the next lexeme is successfully applied, the internal path becomes: + `root -> [Directory] -> [0] -> [children] -> [0]` The meaning of `[-n]` and `[^n]` notation then is easy to observe on this diagram: ``` etc. @@ -1214,7 +1214,7 @@ to address a parent from the root: [^0] [^1] [^2] [^3] [^4 | | | | | to address a parent from the leaf: [-4] [-3] [-2] [-1] [-0] [-5] - etc. + etc. ``` @@ -1276,7 +1276,7 @@ bash $ the result will vary: - `-j` without `-l` will just arrange walked entries into a JSON array: ```bash - bash $ l:' -w'l:' -nj + bash $ l:' -w'l:' -nj [ "John", "Ivan", @@ -1305,7 +1305,7 @@ the result will vary: { "number": "358-303-0373" }, { "number": "333-638-0238" } ] - bash $ + bash $ ``` Though even that behavior is influenced by the `-n` option, the above output looks dull and hardly will have many use-cases, a lot more often it's required to group relevant walks together and then place them into respective JSON structures. For that, let's review @@ -1328,7 +1328,7 @@ bash $ l:' -w'l:' bash $ ``` Those look interleaved, though it does not appear that they relate to each other properly: e.g.: a number `"113-123-2368"` -belong to `"John"` and preferably should be displayed before `"Ivan"` and so does apply to others. `jtc` is capable of +belong to `"John"` and preferably should be displayed before `"Ivan"` and so does apply to others. `jtc` is capable of processing/printing relevant entries, though it needs a little hint from the walk-paths: the latter supposed to express the relation between themselves. @@ -1365,7 +1365,7 @@ bash $ l:' -w'[Directory][:]l:' -jl "number": [ "358-303-0373", "333-638-0238" ] } ] -bash $ +bash $ ``` B.t.w., the relation between walks could be also expressed in a _relative_ (rather than via _absolute_, as above) path way: ```bash @@ -1379,7 +1379,7 @@ bash $ l:' -w'l:[-1]l:' "Jane" "358-303-0373" "333-638-0238" -bash $ +bash $ # and now groping relevant walks: bash $ l:' -w'l:[-1]l:' -jl -tc [ @@ -1396,7 +1396,7 @@ bash $ l:' -w'l:[-1]l:' -jl -tc "number": [ "358-303-0373", "333-638-0238" ] } ] -bash $ +bash $ ``` >Note: such grouping is only possible with labeled values (obviously), it won't be possible to group array elements that easily, > e.g., let's break array into pairs: @@ -1404,13 +1404,13 @@ bash $ >bash $ array='[0,1,2,3,4,5,6,7,8,9]' >bash $ <<<$array jtc -w[::2] -w[1::2] -j -tc >[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] ->bash $ +>bash $ >``` > it won't work even if we try relating walks: >```bash >bash $ <<<$array jtc -w[::2] -w'[::2]k[-1]>I[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] ->bash $ +>bash $ >``` >Thus grouping here should be achieved differently. One way is to use only a single walk collecting required elements of the group into >the namespaces and then using template interpolating the latter: @@ -1435,7 +1435,7 @@ bash $ > "6": [ 6, 7 ], > "8": [ 8, 9 ] >} ->bash $ +>bash $ >``` >and then re-walk dropping labels and encapsulating into the outer array: >```bash @@ -1447,7 +1447,7 @@ bash $ > [ 6, 7 ], > [ 8, 9 ] >] ->bash $ +>bash $ #### Aggregating walks @@ -1471,7 +1471,7 @@ bash $ l:' -w'[Directory][:]l:' -jln ] } ] -bash $ +bash $ ``` @@ -1493,10 +1493,10 @@ bash $ [-1]<>a:' -jj "street address": "6213 E Colfax Ave", "type": "home" } -bash $ +bash $ ``` Well, the above output though does not keep all the atomic entries from the Jane's record (e.g.: Jane has 2 phone numbers, while only -one is displayed). That is because clashing labels will override each other (as of version _1.75_). To ensure aggregation of clashing +one is displayed). That is because clashing labels will override each other (as of version _1.75_). To ensure aggregation of clashing labels, use `-m` option: ```bash bash $ [-1]<>a:' -jjm @@ -1517,9 +1517,9 @@ bash $ [-1]<>a:' -jjm "home" ] } -bash $ +bash $ ``` -As one can see, even though `Jane` has 2 lovely children (`Robert` and `Lila`), they were not listed on the resulting output, +As one can see, even though `Jane` has 2 lovely children (`Robert` and `Lila`), they were not listed on the resulting output, that is because they are enlisted in _JSON array_ and therefore have no labels (and hence ignored in `-jj` option, which considers values with labels only). @@ -1528,7 +1528,7 @@ values with labels only). Sometimes, when displaying outputs wrapped into an object, it's desirable to extract the labeled value from the object (i.e., reach inside the object and use inner label rather than outer). This become especially handy when dealing with templates. -Let's consider a following query: +Let's consider a following query: Say, the ask here is to extract all names of all the people from `ab.json` and group them with newly crafted record indicating if a person has children or not, like this: ```bash @@ -1544,10 +1544,10 @@ bash $ l:' "John" "Ivan" "Jane" -bash $ +bash $ ``` -2\. Crafting a new record would require knowing +2\. Crafting a new record would require knowing [templates](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#templates), [namespace](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#namespace) and [interpolation](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#interpolation) @@ -1560,18 +1560,18 @@ bash $ l:' -w'l: f[0]v' [] "Jane" "Robert" -bash $ +bash $ ``` \- the second walk above features couple concepts: - [branching](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#fail-safe-and-forward-stop-directives) -(`<..>f`) _fail-safe_ lexeme: ensures that the walk is reinstated at the placement of the lexeme if/once the +(`<..>f`) _fail-safe_ lexeme: ensures that the walk is reinstated at the placement of the lexeme if/once the subsequent walk fails - [namespaces](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#namespace) -(`f`, `v`): both lexemes setup the _namespace_ `C`, initially to value `"no"` then to value `"yes"`; +(`f`, `v`): both lexemes setup the _namespace_ `C`, initially to value `"no"` then to value `"yes"`; the latter value will override the former only if walking `[0]` was successful (i.e., if a person indeed has at least one child, b/c if array `children` were empty, that walk would fail) -3\. by now, each time when second walk finishes iteration, the namespace `C` should be correctly populated with the respective values +3\. by now, each time when second walk finishes iteration, the namespace `C` should be correctly populated with the respective values reflecting if a person has children or not, but to see that, we'd need to interpolate that namespace using a template: ```bash bash $ l:' -w'l: f[0]v' -TT -T'{"has children": {{C}}}' -tc @@ -1581,18 +1581,18 @@ bash $ l:' -w'l: f[0]v' -TT -T'{"ha { "has children": "no" } "Jane" { "has children": "yes" } -bash $ +bash $ ``` 4. okay, we're getting closer, but now we want to display all records with labels: ```bash bash $ l:' -w'l:f[0]v' -T'{"has children": {{C}}}' -l "name": "John" jtc jnode exception: label_accessed_not_via_iterator -bash $ +bash $ ``` -Bummer! The exception (rightfully) occurs here because trying to find an outer label (with `-l`) of an interpolated JSON -`{ "has children": "yes" }` fails - indeed it's a standalone JSON, and root does not have any label attached - hence the -exception. In the situations like this, we'd rather want to reach out inside the object for a labeled value rather than +Bummer! The exception (rightfully) occurs here because trying to find an outer label (with `-l`) of an interpolated JSON +`{ "has children": "yes" }` fails - indeed it's a standalone JSON, and root does not have any label attached - hence the +exception. In the situations like this, we'd rather want to reach out inside the object for a labeled value rather than finding an outer label. The option `-ll` facilitates that requirement: ```bash bash $ l:' -TT -w'l: f[0]v' -T'{"has children": {{C}}}' -llj -tc @@ -1601,11 +1601,11 @@ bash $ l:' -TT -w'l: f[0]v' -T'{"ha { "has children": "no", "name": "Ivan" }, { "has children": "yes", "name": "Jane" } ] -bash $ +bash $ ``` -Finally, what's `-TT` in there? That's a dummy template (one which surely fails). It's needed because if it wasn't here, then +Finally, what's `-TT` in there? That's a dummy template (one which surely fails). It's needed because if it wasn't here, then a single template would apply to both walks (and we don't want our template to apply onto the first walk). So, we'd rather -provide a dummy one so that each +provide a dummy one so that each [template would relate to own walk](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#multiple-templates-and-walks). If template fails (and `-TT` surely does) then no interpolation applied and walk iteration result is used as it is. @@ -1619,13 +1619,13 @@ bash $ l:' -w'l: f[0]v' -T'{"has ch { "has children": "no" } { "has children": "no" } { "has children": "yes" } -bash $ +bash $ ``` Now, the same template (`-T'{"has children": {{C}}}'`) gets applied to each walk, and while for the 1st walk the template interpolation definitely fails (while walking the 1st walk iteration for the 1st time, the name `C` does not exist yet in the namespace) and therefore the very 1st walk is getting displayed as it is, for all the subsequent iterations of the 1st walk the template interpolation would succeed (because the namespace `C` now holds the value from the 2nd walk) and therefore -unwanted template substitution occurs. +unwanted template substitution occurs. To fix that problem easily, we can erase the namespace `C` right at the beginning of the 1st walk: ```bash bash $ zl:' -w'l: f[0]v' -T'{"has children": {{C}}}' -tc @@ -1635,7 +1635,7 @@ bash $ zl:' -w'l: f[0]v' -T'{"ha { "has children": "no" } "Jane" { "has children": "yes" } -bash $ +bash $ ``` And adding `-llj` provides the desired effect now: ```bash @@ -1645,11 +1645,11 @@ bash $ zl:' -w'l: f[0]v' -T'{"ha { "has children": "no", "name": "Ivan" }, { "has children": "yes", "name": "Jane" } ] -bash $ +bash $ ``` > all the above examples just illustrate capabilities of the options for instructional purpose. Practically, -the same ask would be easier to achive using just a single walk: +the same ask would be easier to achive using just a single walk: >```bash >bash $ l:v[-1][children]f[0]v' -T'{"name":{{N}}, "has children": {{C}}}' -jtc >[ @@ -1657,15 +1657,15 @@ the same ask would be easier to achive using just a single walk: > { "has children": "no", "name": "Ivan" }, > { "has children": "yes", "name": "Jane" } >] ->bash $ +>bash $ >``` #### Succinct walk-path syntax If you look at the prior example ([Aggregating walks](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#aggregating-walks)), -you may notice that a common part of both walk-paths (`[Directory][:]`) had been given twice. There's a way to express it in a more -succinct syntax: options `-x` and `-y` allow rearranging walk-paths so that `-x` takes an initial common part of the walk-path, +you may notice that a common part of both walk-paths (`[Directory][:]`) had been given twice. There's a way to express it in a more +succinct syntax: options `-x` and `-y` allow rearranging walk-paths so that `-x` takes an initial common part of the walk-path, whereas `-y` would take care of the varying trailing pars. Thus the same example cold have been written like this: ```bash bash $ l:' -y'l:' -jlnn @@ -1688,7 +1688,7 @@ bash $ l:' -y'l:' -jlnn ] ``` \- each occurrence of `-x` will be reconciled with all subsequent `-y` (until next `-x` is faced). Options `-x`, `-y` is merely -a syntactical sugar and do not apply any walk-path parsing or validation, instead they just reconcile into respective `-w` options +a syntactical sugar and do not apply any walk-path parsing or validation, instead they just reconcile into respective `-w` options created internally, then the latter get processed. Thus, it's even possible to write it with what it seems a broken syntax at first: ```bash bash $ l:' -y']l:' -jlnn @@ -1697,7 +1697,7 @@ bash $ l:' -y']l:' -jlnn However, if a reinstatement of the options results in a valid walk-path - that's all what matters. It's possible to combine both syntaxes (e.g.: `-w` with `-x` and `-y`), however, given that the processing of `-x` and `-y` -internally reinstates respective options `-w`, the former will be appended after any of given `-w` options (which will affect the +internally reinstates respective options `-w`, the former will be appended after any of given `-w` options (which will affect the order of processing/outputting) even though the order of their appearance is different: ```bash bash $ l:' -y'l:' -w 'l:' -rnl @@ -1715,7 +1715,7 @@ bash $ l:' -y'l:' -w ' remember: the second number in the option is an index and thus is zero based @@ -1773,12 +1773,12 @@ bash $ <<<$jsn jtc -w[:] -x4/2 -x/0 -x/-1 3 7 9 -bash $ +bash $ ``` ### Summary table of search lexemes -sfx | Empty lexeme semantic (`<>`) | Non-empty semantic (`<..>`) | Semantic with namespace assignment (``) +sfx | Empty lexeme semantic (`<>`) | Non-empty semantic (`<..>`) | Semantic with namespace assignment (``) --- | :--- | :--- | :--- _r_ | `<>` matches _empty string_ (`""`) | `` matches given _string_ `"str"` | - _R_ | - | `R` matches _string value_ using _REGEX_ `RE` | - @@ -1796,7 +1796,7 @@ _i_ | `<>i` matches any _array_ value | `i` stores (_any_) found _array val _c_ | `<>c` matches any _container_ (_object_ or _array_) value | `c` stores (_any_) found _container value_ in the namespace `val` | `c` upon any _container match_ stores in the namespace `v` a user's value _e_ | `<>e` matches any _end node_ (_atomic_ or _[]_ or _{}_) value | `e` stores (_any_) found _end node value_ in the namespace `val` | `e` upon any _end node match_ stores in the namespace `v` a user's value _w_ | `<>w` matches _any_ JSON value | `w` stores _any_ found value in the namespace `val` | `w` upon any value match stores in the namespace `v` a user's value -_j_ | - | `j` matches literal _JSON_ (`JSN` could be also a template) | - +_j_ | - | `j` matches literal _JSON_ (`JSN` could be also a template) | - _s_ | - | `s` matches a _JSON value_ previously stored in the namespace `val` | - _t_ | - | `t` matches a _label_ or _index_ previously stored in the namespace `val` | - _q_ | `<>q` - matches an _original_ (_non-duplicating_) value | `q` stores (_any_) found _original value_ in the namespace `val` | `q` upon an _original value match_ stores in the namespace `v` a user's value @@ -1834,16 +1834,16 @@ matches _every child_ in a currently walked JSON _iterable_ starting from _`N`th - [`[N:M:S]`](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#subscript-slice-notation): matches _every child_ in a currently walked JSON _iterable_ starting from _`N`th_ child up till, but not including _`M`th_ with the step of _`S`_ (`N`,`M` could be negative defining the start/end of the slice from the end of the _iterable_ rather than from -the start, while _`S`_ can only be positive); either of positional parameters could be omitted (e.g.: +the start, while _`S`_ can only be positive); either of positional parameters could be omitted (e.g.: `[:]`, `[::]`, `[1:]`, `[:-2]`, `[::3]`, etc) - [`<>`](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#searching-json): finds recursively the first _empty string_ (e.g.: like in `{ "empty string": "" }`) - [``](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#searching-json): finds _recursively_ the first string _`"text"`_ (e.g.: like in `[ "text" ]`) - [`<..>X`](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#search-suffixes): -_`X`_ is an optional one-letter suffix altering the behavior of the lexeme: - * if _`X`_ is any of _`rRPdDNbnlLaoicewjstqQgG`_ - then it's a _search_ matching a first occurrence of the lexeme, as per the - suffix description +_`X`_ is an optional one-letter suffix altering the behavior of the lexeme: + * if _`X`_ is any of _`rRPdDNbnlLaoicewjstqQgG`_ - then it's a _search_ matching a first occurrence of the lexeme, as per the + suffix description * if _`X`_ is any of _`vkzfFuIZWS`_ then it's a _directive_ and applies the respective behavior as per the suffix description - [`n`](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#search-quantifiers): finds recursively _`n`th_ occurrence of _`"text"`_ in a currently walked JSON element @@ -1853,12 +1853,12 @@ finds recursively _each occurrence_ of _`"text"`_ in a currently walked JSON ele finds recursively _each occurrence_ of `"text"` in a currently walked JSON element for the selected slice, where _`n`_,_`m`_,_`s`_ parameters comply with all `[N:M:S]` rules with an additional limitation: _`n`_ and _`m`_ cannot go negative and one additional liberation: either of parameters _`n`_,_`m`_,_`s`_ could be _interpolated_ from the namespace -- [`<..>Xn`, `<..>X+n`, `<..>Xn:m:s`](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#search-quantifiers): +- [`<..>Xn`, `<..>X+n`, `<..>Xn:m:s`](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#search-quantifiers): * if _`X`_ is a search lexeme suffix, then quantifier notations apply exactly the same way as per in above `text` search quantifiers - * if _`X`_ is a directive lexeme suffix, then the quantifier behavior is either ignored (like in directives `vkzW`), + * if _`X`_ is a directive lexeme suffix, then the quantifier behavior is either ignored (like in directives `vkzW`), or is specific for the given directive (refer to the relevant description of directives: `fFuIZ`) - [`[label]:<..>`](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#scoped-search): -_scoped_ recursive search - the search and match is performed in the currently selected JSON element only _among +_scoped_ recursive search - the search and match is performed in the currently selected JSON element only _among values with the specified label_; directives lexemes ignore scoping; all search suffixes and quantifiers are applicable in the scoped searches - [`>..<`](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#non-recursive-search): @@ -1879,10 +1879,10 @@ suffixes exemptions: some search lexemes and some directives allow _capturing_ a currently walked/matched JSON into a namespace _`NS`_: * if _`X`_ is a suffix any of _`PNbnaoicewqQgGvfF`_, then the namespace _`NS`_ will be populated upon a successful match (for searches) or upon walking (for directives) - * for the rest of the searches (_`rRdDlLjst`_), the lexeme defines a _search context_ (rather than the namespace reference), + * for the rest of the searches (_`rRdDlLjst`_), the lexeme defines a _search context_ (rather than the namespace reference), * for for the rest of directives (_`kzuIZWS`_) the behavior varies - refer to a respective directive description - [`X`](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#setting-a-custom-json-value-into-a-namespace): -the same searches and directives allowing _capturing_ JSON values, allow setting custom _`JSON_value`s_ +the same searches and directives allowing _capturing_ JSON values, allow setting custom _`JSON_value`s_ _instead_ of capturing (the same rules apply) @@ -1892,19 +1892,19 @@ defines a _walk-path_ (multiple walks supported), by default the results produce - [`-l`](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#displaying-walks-with-labels): when used w/o `-j` just _prints labels_ for those walked JSONS which have one - [`-ll`](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#extracting-labeled-values): -when used w/o `-j` prints all JSON objects _"naked"_, i.e. _removes JSON object encasement_ and then uses _inner_ labels; +when used w/o `-j` prints all JSON objects _"naked"_, i.e. _removes JSON object encasement_ and then uses _inner_ labels; for the rest of JSON types the behavior is the same like with the single `-l` - [`-n`](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#sequential-walk-processing): turns on a _sequential_ behavior for walk-paths (process first all the results from the first walk, then from then second, etc), - [`-nn`](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#aggregating-walks): when used together with `-j` and `-l` allows _aggregated_ behavior for values with clashing labels, see below - [`-nn`](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#multiple-templates-and-walks): -also triggers a _round-robin templates_ application when a number of templates (`-T`) and walks (`-w`) is the same but +also triggers a _round-robin templates_ application when a number of templates (`-T`) and walks (`-w`) is the same but the _round_robin_ template application must be favored over the _per-walk_'s in this situation - [`-j`](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#wrapping-resulted-walks-to-json-array): arranges all walked elements (from all walk-paths) into a _JSON array_ - [`-jl`](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#wrapping-resulted-walks-to-json-array): -arranges all walked elements (from all walk-paths) into a _JSON array_, puts labeled nodes into _separate JSON objects_, +arranges all walked elements (from all walk-paths) into a _JSON array_, puts labeled nodes into _separate JSON objects_, any clashing labels will be aggregated (into _JSON arrays_) within those objects - [`-jln`](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#wrapping-resulted-walks-to-json-array): arranges all walked elements into a _JSON array_, each labeled element will be placed into _own JSON object_, thus dodging @@ -1916,13 +1916,13 @@ labels are aggregated arranges all walked elements into a _JSON object_ (i.e. all walked elements which do not have labels will be ignored), the values with clashing labels will _override the prior_ values (_note:_ `-l`,`-n` and `-nn` with `-jj` have no effect) - [`-jjm`](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#wrapping-walked-entries-into-a-json-object): -alters behavior of `-jj` by enabling the aggregation of the values with the clashing labels into _JSON arrays_ +alters behavior of `-jj` by enabling the aggregation of the values with the clashing labels into _JSON arrays_ - `-jjll`: combined behavior of `-jj` and `-ll` - `-jjllm`: combined behavior of `-jj` and `-ll` and `-m` - [`-x`,`-y`](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#succinct-walk-path-syntax): facilitates breaking walk-paths (`-w`) into a common (`-x`) and variables parts (`-y`); i.e. an argument of each `-x` will be combined with every subsequent argument of `-y` (if any), e.g.: `-xA` `-yB` `-yC` `-xD` `-yE` `-yF` result in 4 walk-paths: -`-wAB` `-wAC` `-wDE` `-wDF` - thus `-x`/`-y` notation provides more succinct notation (than `-w`) for multiple walk-paths with +`-wAB` `-wAC` `-wDE` `-wDF` - thus `-x`/`-y` notation provides more succinct notation (than `-w`) for multiple walk-paths with a common head (and varying tails) - [`-xN/M`](https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md#controlling-displayed-walks): controls which walk result(s) get(s) printed: print each _`N`th_ walk starting with _`M`th_ (_`M`_ is an index and hence is @@ -1951,18 +1951,18 @@ otherwise the template will fail to get applied ### Interpolation token types -The difference between single `{}` and double `{{}}` notations: +The difference between single `{}` and double `{{}}` notations: - double notation (a.k.a. _dressed notation_) `{{..}}` interpolates JSON elements exactly, so it's always a safe type - a single notation (a.k.a. _naked notation_) `{..}` "strips" the interpolated object and interpolates _JSON strings_, _JSON arrays_, _JSON objects_ differently: - * when interpolating _JSON string_, the outer quotation marks are dropped, e.g., instead of `"blah"`, it will be interpolated as + * when interpolating _JSON string_, the outer quotation marks are dropped, e.g., instead of `"blah"`, it will be interpolated as `blah`. Thus, it makes sense to use this interpolation inside double quotation marks - * when interpolating _JSON array_, then enclosing brackets `[`, `]` are dropped (allows extending arrays); e.g., `[1,"2",{}]` + * when interpolating _JSON array_, then enclosing brackets `[`, `]` are dropped (allows extending arrays); e.g., `[1,"2",{}]` will be interpolated as `1,"2",{}` (which is invalid JSON), thus, to keep it valid the outer brackets must be provided, e.g.: `-T'[ 0, {}, 4, [] ]'` after becomes `[ 0, 1, "2", {}, 4, [] ]` - * when interpolating _JSON object_, then enclosing braces `{`, `}` are dropped (allows extending objects), e.g., `{"pi":3.14}` + * when interpolating _JSON object_, then enclosing braces `{`, `}` are dropped (allows extending objects), e.g., `{"pi":3.14}` will be interpolated as `"pi": 3.14`, so to keep it valid the outer braces must be provided, e.g., `-T'{ {}, "type": "irrational" }'` - * if you meant to insert in a template an empty object `{}` rather than a _naked_ token (which has the same notation), + * if you meant to insert in a template an empty object `{}` rather than a _naked_ token (which has the same notation), then spell it over space: `{ }` #### String interpolation @@ -1975,12 +1975,12 @@ bash $ <<<$jsn jtc -w'