Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
174 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
# jsonptr | ||
|
||
This program has two goals: | ||
|
||
1. be a production-quality [JSON](https://json.org/) formatter (pretty-printer) | ||
that supports the JSON Pointer (RFC 6901) query syntax. | ||
2. demonstrate how to use [Wuffs' low-level JSON parsing C | ||
API](https://nigeltao.github.io/blog/2020/jsonptr.html). An alternative, | ||
higher-level C++ API is used in the sibling | ||
[example/jsonfindptrs](/example/jsonfindptrs) program. | ||
|
||
|
||
## Building | ||
|
||
It has no dependencies other than Wuffs. | ||
|
||
$ gcc -O3 jsonptr.cc -o jsonptr | ||
|
||
|
||
## Example | ||
|
||
$ grep foo ../../test/data/rfc-6901-json-pointer.json | ||
"foo": ["bar", "baz"], | ||
$ ./jsonptr -query=/foo/1 ../../test/data/rfc-6901-json-pointer.json | ||
"baz" | ||
|
||
It also supports the JWCC ([JSON With Commas and | ||
Comments](https://nigeltao.github.io/blog/2021/json-with-commas-comments.html)) | ||
syntax. | ||
|
||
$ echo '/* Note the commas. */[1,2,[30,31]]' | ./jsonptr -jwcc | ||
/* Note the commas. */ | ||
[ | ||
1, | ||
2, | ||
[ | ||
30, | ||
31, | ||
], | ||
] | ||
|
||
|
||
## Usage | ||
|
||
$ ./jsonptr -help | ||
Usage: jsonptr -flags input.json | ||
|
||
Flags: | ||
-c -compact-output | ||
-d=NUM -max-output-depth=NUM | ||
-q=STR -query=STR | ||
-s=NUM -spaces=NUM | ||
-t -tabs | ||
-fail-if-unsandboxed | ||
-input-allow-comments | ||
-input-allow-extra-comma | ||
-input-allow-inf-nan-numbers | ||
-input-jwcc | ||
-jwcc | ||
-output-comments | ||
-output-extra-comma | ||
-output-inf-nan-numbers | ||
-strict-json-pointer-syntax | ||
|
||
The input.json filename is optional. If absent, it reads from stdin. | ||
|
||
---- | ||
|
||
jsonptr is a JSON formatter (pretty-printer) that supports the JSON | ||
Pointer (RFC 6901) query syntax. It reads UTF-8 JSON from stdin and | ||
writes canonicalized, formatted UTF-8 JSON to stdout. | ||
|
||
Canonicalized means that e.g. "abc\u000A\tx\u0177z" is re-written | ||
as "abc\n\txŷz". It does not sort object keys, nor does it reject | ||
duplicate keys. Canonicalization does not imply Unicode normalization. | ||
|
||
Formatted means that arrays' and objects' elements are indented, each | ||
on its own line. Configure this with the -c / -compact-output, -s=NUM / | ||
-spaces=NUM (for NUM ranging from 0 to 8) and -t / -tabs flags. | ||
|
||
The -input-allow-comments flag allows "/*slash-star*/" and | ||
"//slash-slash" C-style comments within JSON input. Such comments are | ||
stripped from the output unless -output-comments was also set. | ||
|
||
The -input-allow-extra-comma flag allows input like "[1,2,]", with a | ||
comma after the final element of a JSON list or dictionary. | ||
|
||
The -input-allow-inf-nan-numbers flag allows non-finite floating point | ||
numbers (infinities and not-a-numbers) within JSON input. This flag | ||
requires that -output-inf-nan-numbers also be set. | ||
|
||
The -output-comments flag copies any input comments to the output. It | ||
has no effect unless -input-allow-comments was also set. Comments look | ||
better after commas than before them, but a closing "]" or "}" can | ||
occur after arbitrarily many comments, so -output-comments also requires | ||
that one or both of -compact-output and -output-extra-comma be set. | ||
|
||
With -output-comments, consecutive blank lines collapse to a single | ||
blank line. Without that flag, all blank lines are removed. | ||
|
||
The -output-extra-comma flag writes output like "[1,2,]", with a comma | ||
after the final element of a JSON list or dictionary. Such commas are | ||
non-compliant with the JSON specification but many parsers accept them | ||
and they can produce simpler line-based diffs. This flag is ignored when | ||
-compact-output is set. | ||
|
||
Combining some of those flags results in speaking JWCC (JSON With Commas | ||
and Comments), not plain JSON. For convenience, the -input-jwcc or -jwcc | ||
flags enables the first two or all four of: | ||
-input-allow-comments | ||
-input-allow-extra-comma | ||
-output-comments | ||
-output-extra-comma | ||
|
||
---- | ||
|
||
The -q=STR or -query=STR flag gives an optional JSON Pointer query, to | ||
print a subset of the input. For example, given RFC 6901 section 5's | ||
sample input (https://tools.ietf.org/rfc/rfc6901.txt), this command: | ||
jsonptr -query=/foo/1 rfc-6901-json-pointer.json | ||
will print: | ||
"baz" | ||
|
||
An absent query is equivalent to the empty query, which identifies the | ||
entire input (the root value). Unlike a file system, the "/" query | ||
does not identify the root. Instead, "" is the root and "/" is the | ||
child (the value in a key-value pair) of the root whose key is the empty | ||
string. Similarly, "/xyz" and "/xyz/" are two different nodes. | ||
|
||
If the query found a valid JSON value, this program will return a zero | ||
exit code even if the rest of the input isn't valid JSON. If the query | ||
did not find a value, or found an invalid one, this program returns a | ||
non-zero exit code, but may still print partial output to stdout. | ||
|
||
The JSON specification (https://json.org/) permits implementations that | ||
allow duplicate keys, as this one does. This JSON Pointer implementation | ||
is also greedy, following the first match for each fragment without | ||
back-tracking. For example, the "/foo/bar" query will fail if the root | ||
object has multiple "foo" children but the first one doesn't have a | ||
"bar" child, even if later ones do. | ||
|
||
The -strict-json-pointer-syntax flag restricts the -query=STR string to | ||
exactly RFC 6901, with only two escape sequences: "~0" and "~1" for | ||
"~" and "/". Without this flag, this program also lets "~n", | ||
"~r" and "~t" escape the New Line, Carriage Return and Horizontal | ||
Tab ASCII control characters, which can work better with line oriented | ||
(and tab separated) Unix tools that assume exactly one record (e.g. one | ||
JSON Pointer string) per line. | ||
|
||
---- | ||
|
||
The -d=NUM or -max-output-depth=NUM flag gives the maximum (inclusive) | ||
output depth. JSON containers ([] arrays and {} objects) can hold other | ||
containers. When this flag is set, containers at depth NUM are replaced | ||
with "[…]" or "{…}". A bare -d or -max-output-depth is equivalent to | ||
-d=1. The flag's absence is equivalent to an unlimited output depth. | ||
|
||
The -max-output-depth flag only affects the program's output. It doesn't | ||
affect whether or not the input is considered valid JSON. The JSON | ||
specification permits implementations to set their own maximum input | ||
depth. This JSON implementation sets it to 1024. | ||
|
||
Depth is measured in terms of nested containers. It is unaffected by the | ||
number of spaces or tabs used to indent. | ||
|
||
When both -max-output-depth and -query are set, the output depth is | ||
measured from when the query resolves, not from the input root. The | ||
input depth (measured from the root) is still limited to 1024. | ||
|
||
---- | ||
|
||
The -fail-if-unsandboxed flag causes the program to exit if it does not | ||
self-impose a sandbox. On Linux, it self-imposes a SECCOMP_MODE_STRICT | ||
sandbox, regardless of whether this flag was set. |