├── CHANGELOG.MD ├── LICENSE ├── README.md └── sources ├── jpt └── jpt.min /CHANGELOG.MD: -------------------------------------------------------------------------------- 1 | ### jpt (JSON Power Tool) 2 | 3 | ### Change Log 4 | 5 | ### v1.0.9 6 | * Fixed issue with the [JSONPath engine](https://github.com/brunerd/jsonpath) that caused object members named `values` with an array as the value, to return malformed paths ending in a `[NaN]` 7 | 8 | ### v1.0.8 9 | * `OPTIND` and `OPTARG` now declared as **local** variables within `jpt` due to issues when embedded in `bash` scripts which uses global variables for them that are not sanitized within functions as it is for `zsh` 10 | 11 | * Minified version (jpt.min) was not ES5 due to [changes in Closure](https://github.com/google/closure-compiler/wiki/Releases#november-7-2021-v20211107) (my bad) this caused issues in macOS 10.15 and under, this has been addressed. 12 | 13 | ### v1.0.7 14 | * Reverted back to standard `/usr/bin` sh-bang paths, using `env` can cause issues with upgraded shells 15 | 16 | ### v1.0.6b 17 | * Textual output (-T) now escapes solidus/backslashes \\ with \\\\, when encoding (-E) for escaped formats (hex, octal, Unicode code points) or if whitespace escaping (-e) is specified but without -E encoding. 18 | 19 | ### v1.0.5 20 | * fixed handling of keypaths with multiple escaped periods 21 | 22 | ### v1.0.4 23 | * Support and refinements for JSONPath "existence test" in filter expressions for nodes that contain data that evaluates as "falsey" (e.g. zero, negative numbers, empty strings, null, and false). 24 | * Negation operator (!) now works on both existence tests and standard comparison operations in filter expressions 25 | 26 | * For example: 27 | ``` 28 | % jpt -i0 '$[?(@.falsey)]' <<< '[{"falsey":0}]' 29 | {"falsey":0} 30 | 31 | % jpt -i0 $'$[?(!@.a && !@.b)]' <<< '[{"a":5,"b":9},{"c":3,"d":4}]' 32 | {"c":3,"d":4} 33 | ``` 34 | * `-W` flag to also encode whitespace when outputting encoded text with `-T` and `-E ` where the modes typically only encodes non-ASCII text, for example octal output suitable for fstab: 35 | ``` 36 | % jpt -S -W -T -EO <<< 'Macintosh HD' 37 | Macintosh\040HD 38 | ``` 39 | * Fixed bug in [closure](https://mvnrepository.com/artifact/com.google.javascript/closure-compiler) compiled minified version that affected filters. Now using whitespace only compilation level. 40 | * More forgiving of `jq`-isms in queries: a single `.` acts as root, `.[` at the beginning is treated as `$[` 41 | ##### v1.0.3 (this is not the release you are looking for) 42 | 43 | ### v1.0.2 44 | * Disables xtrace while inside the function for quieter debugging of your scripts 45 | * plutil-style keypaths are now accepted 46 | * jq-style paths that begin with `[` or `.` are now accepted (jq pipes `|` are _not_ support) 47 | * `jpt` function now runs in a subshell, so shell variables no longer need use `local` to avoid name collisions with global variables 48 | * Cleanup of shell syntax for `test` from chained `-a` and `-o` style boolean operators to discrete `&&` and `||` expressions 49 | 50 | ### v1.0.1 51 | * Help text from `jpt -h` now pipes through `less` for pagination (and has one less typo!) 52 | * If no inputs are detected (via file path, pipe, or file redirection) `jpt` displays info and exits instead of waiting for input 53 | ``` 54 | % jpt 55 | jpt (v1.0.1) - JSON Power Tool (https://github.com/brunerd/jpt) 56 | Usage: jpt [options] [query] [filepath] (see jpt -h for more help...) 57 | ``` 58 | * Fixes pkg installer bug if `/usr/local/bin` did not exist 59 | 60 | ### v1.0.0 bug fixes and enhancements 61 | Notable new features include: 62 | * The ability to parse and generate JSON Text Sequences, NDJSON/JSON Lines, and "concatenated JSON" 63 | * The ability to parse "JSON5" and rehabilitate back to JSON with conversion options for NaN and Infinity number types 64 | * Two new merge modes: `merge0` to merge object properties that DO NOT intersect with source JSON and `merge1` to merge only ones that **do** 65 | * Revamped hex, binary and octal numeric encoding modes using ECMAScript notation 66 | * Continued support for JSONPath object literals (-L mode) now with record separator support for multiple JSON texts 67 | * Truncated JSON can be detected and capped for recovery. 68 | 69 | Read more about jpt at: [https://www.brunerd.com/blog/category/projects/jpt/](https://www.brunerd.com/blog/category/projects/jpt/) 70 | 71 | **Installation Notes**: The package is _not_ notarized (because it breaks on older macOS). Simply right-click in Finder and choose Open to allow Gatekeeper bypass. You can also remove the quarantine by opening Terminal and running this command: `xattr -rc ` 72 | 73 | The installer pkg includes both the full script (jpt) and the minified version (jpt.min) installed to /usr/local/jpt/ with a soft link to jpt created in /usr/local/bin. The minified version `jpt.min` is for easy inclusion in _your_ shell scripts while `jpt` is for standalone use. 74 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Joel Bruner 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jpt 2 | JSON Power Tool: Query and manipulate JSON and JSON Text Sequences using [JSONPath](https://datatracker.ietf.org/doc/draft-ietf-jsonpath-base/), [JSON Pointer](https://tools.ietf.org/html/rfc6901), [JSON Patch](http://tools.ietf.org/html/rfc6902), and [JSON Merge Patch](https://tools.ietf.org/html/rfc7386). 3 | 4 | Written in Javascript (ES5) and wrapped in a bit of shell, it can be used standalone or embedded in your bash/zsh scripts, requiring only `jsc` which has been standard on Macs since 10.4 and is widely available for Linux and even Windows with Linux subsystem installed. 5 | 6 | It is a non-compiled script, so it can be easily studied, maintained, or modified. It avoids the need for code-signing and notarization on the Mac platform. 7 | 8 | See my blog for articles, examples, and musing on the jpt: https://www.brunerd.com/blog/category/projects/jpt/ 9 | 10 | ## Examples 11 | Please see the [brunerd JSONPath](https://github.com/brunerd/jsonpath) GitHub page for an *extensive* list of example JSONPath queries. 12 | 13 | [JSONPath](https://datatracker.ietf.org/doc/draft-ietf-jsonpath-base/) has a richly expressive syntax that can query the contents of JSON in ways JSON Pointer can't. For example **filter expressions** can find objects within an array: 14 | ``` 15 | % jpt '$.object_array[?(@.color == "blue")]' <<< '{"object_array":[{"id":2,"color":"red"},{"id":1,"color":"blue"}]}' 16 | { 17 | "id": 1, 18 | "color": "blue" 19 | } 20 | ``` 21 | The values within the found objects can be specifically reported: 22 | ``` 23 | % jpt '$.object_array[?(@.color == "blue")].id' <<< '{"object_array":[{"id":2,"color":"red"},{"id":1,"color":"blue"}]}' 24 | 1 25 | ``` 26 | 27 | [JSON Pointer](https://tools.ietf.org/html/rfc6901) is extremely simple and can query a *single* property only, this uses the `-T` option to print a JSON string as text and not encoded within double quotes. 28 | ``` 29 | % jpt -T /object/array/1/mood <<< $'{"object":{"array":[{"mood":"excited"},{"mood":"intrigued"}]}}' 30 | intrigued 31 | ``` 32 | 33 | ## Help File (-h) 34 | ``` 35 | jpt (v1.0.9) - JSON Power Tool (https://github.com/brunerd/jpt) 36 | 37 | Usage: 38 | jpt [options] [] [] 39 | 40 | Arguments: 41 | [] - JSONPath, JSON Pointer, or plutil-style keypath expression (optional), returns entire document otherwise. 42 | [] - path to JSON file 43 | 44 | Notes: 45 | Default output mode is JSON (RFC8259/STD90) 46 | Multiple JSON texts will be output as a JSON Text Sequence (RFC 7464) (use -M to change behavior and processing) 47 | jpt accepts input by file redirection, Unix pipe, here string, heredoc and via /dev/stdin (end with Control-D) 48 | jpt accepts JSON, JSON text Sequences, and non-JSON mutations such as JSON5, NDJSON and jpt's own JSONPath Object Literals 49 | JSON Text Sequences will be strictly parsed to RFC 7464 specs, non-JSON elements are only tolerated in single and concatenated JSON texts 50 | Non-JSON elements are corrected automatically, if possible, before parsing (use -c for comments via stderr with an exit status of 1) 51 | JSON5 Rehabilitations (mostly): 52 | Unquoted object keys and single quoted strings are converted to JSON strings 53 | Additional Unicode whitespaces and paragraph separators are converted to normal spaces (0x20) and newlines (0x0A) 54 | Trailing commas are removed from object and array elements 55 | Explicit plus signs on numbers are removed, decimals without leading zeroes are restored 56 | Multi-line strings with escaped line breaks are reverted to standard JSON strings 57 | Literal tabs in strings are removed also 58 | Escaped character conversions: 59 | \0 to null 60 | \v to '\u000c' 61 | JSON5 number type conversions: 62 | NaN to null (use -8 to convert to "NaN" string) 63 | Inifinity to null (use -I to convert to "Infinity" string, with sign if specified) 64 | Single-line (//) and multi-line (/* */) style comments are removed 65 | Additionally multi-line XML () and single line Shell (#), ASM (;), and Lua (--) comments are removed 66 | 67 | General Options: 68 | -h this help screen 69 | 70 | JSON Output Options: 71 | -i "" indent number of spaces (0-10) or use a for each level of indent 72 | -O Order property names in objects alphabetically 73 | -u Unicode escape (\u) all characters above 0x7E 74 | 75 | Advanced JSON Output Options: 76 | -a always output result in an array 77 | -c comment on corrections to non-standard JSON via stderr output (with exit status of 1) 78 | -F Flatten array output 79 | -I Convert JSON5 +/-Infinity value to a string with signedness (otherwise converts to null) 80 | -N Nested single element arrays are reduced 81 | -8 Convert JSON5 NaN to a string (otherwise converts to null) 82 | -/ Escape solidus / with a reverse solidus like \/, useful for HTML with embedded JSON encoded HTML 83 | 84 | Input Options: 85 | -D Detect truncation within objects and arrays in concatenated JSON only 86 | -g path-only JSONPath Object Literals are assigned a value of null ("gratis nulls") 87 | -G Guard previously defined JSONPath Object Literals from being modified by new statements 88 | -H Help truncated JSON by closing up open strings, objects and arrays 89 | -S Treat input as a JSON string 90 | 91 | Multiple JSON Text Options: 92 | -M "" - options for working with multiple JSON texts 93 | S - Output JSON Text Sequences strictly conforming to RFC 7464 (default) 94 | N - Output newline delimited JSON texts 95 | C - Output concatenated JSON texts 96 | A - Gather JSON texts into an array, post-query and post-patching 97 | a - Gather JSON texts into an array, pre-query and pre-patching 98 | 99 | Alternate Output Modes (non-JSON): 100 | -l output the length of the resulting array, object property count, or length of string 101 | 102 | -J JSONPath path(s) of the object returned by the query 103 | -j JSONPath path(s) matched by the query results 104 | 105 | -R JSON Pointer path(s) of the object returned by the query 106 | -r JSON Pointer path(s) matched by the query results 107 | Specifiying -EW or -Ew encodes both -r and -R JSON Pointer paths in URI fragment style 108 | 109 | -J and -R path output options: 110 | -C append the "constructor" type (Array, Object, String, Boolean, Number, or null) 111 | -K/-k print property (key) names and array indices only with no preceding path, default indent is 2 112 | -i "" indent spaces (0-10) or character for each level of indent 113 | 114 | -L JSONPath Object Literal notation output of the resulting object 115 | JPOL Format: = 116 | is simply Javascript expression syntax with $ as the object name 117 | Example: $.key, $["key"], $['key'], or $[0] 118 | is any valid JSON value (plus single quoted strings) 119 | Example: 'string', "string", [], {}, 42, true, false, null 120 | 121 | JSONPath output options for -L -J and -j: 122 | -d Use dot notation for object property names when possible, rather than bracket notation 123 | -q Use single quotes for bracketed property names, string values remain JSON double quoted 124 | -Q Use single quotes for BOTH bracketed property names AND string values (-L only) 125 | -u encode characters above 7E with \u escape 126 | 127 | Output limiting options for -L, -J, and -R: 128 | -P Only print Primitive data types (String, Boolean, Number, null) omitting Arrays and Objects 129 | -Z "" Depth 130 | Combined with -L it will coalesce lower depth levels into a compound JSON object/array statement 131 | Combined with -P both -J and -R will return only purely primitive nodes at or below the Z level 132 | 133 | -T textual output of all data (omits property names and indices) 134 | Options: 135 | -e encode whitespace and escapes: \b \f \n \r \t \v and \\ (\ escaped formats only) 136 | -i "" indent spaces (0-10) or character string for each level of indent 137 | -n convert null value to string 'null' (pre-encoding) 138 | 139 | -E "" encoding options for -T output: 140 | 141 | Encodes string characters below 0x20 and above 0x7E with pass-through for all else: 142 | x "\x" prefixed hexadecimal UTF-8 strings 143 | O "\nnn" style octal for UTF-8 strings 144 | 0 "\0nnn" style octal for UTF-8 strings 145 | u "\u" prefixed Unicode for UTF-16 strings 146 | U "\U "prefixed Unicode Code Point strings 147 | E "\u{...}" prefixed ES2016 Unicode Code Point strings 148 | W "%nn" Web encoded UTF-8 string using encodeURI (respects scheme and domain of URL) 149 | w "%nn" Web encoded UTF-8 string using encodeURIComponent (encodes all components URL) 150 | 151 | -W encodes whitespace characters also 152 | -A encodes ALL characters 153 | 154 | Encodes both strings and numbers with pass-through for all else: 155 | h "0x" prefixed lowercase hexadecimal, UTF-8 strings 156 | H "0x" prefixed uppercase hexadecimal, UTF-8 strings 157 | o "0o" prefixed octal, UTF-8 strings 158 | 6 "0b" prefixed binary, 16 bit _ spaced numbers and UTF-16 strings 159 | B "0b" prefixed binary, 8 bit _ spaced numbers and UTF-16 strings 160 | b "0b" prefixed binary, 8 bit _ spaced numbers and UTF-8 strings 161 | 162 | -U whitespace is left untouched (not encoded) 163 | 164 | Data Processing: 165 | jpt can apply JSON Patch (RFC 6902), JSON Merge Patch (RFC 7396), and other operations to JSON text(s) 166 | 167 | JSON Patch processing: 168 | -X "" a file path to a JSON Patch array (RFC 6902) 169 | -x "" inline JSON Patch text (RFC 6902) 170 | 171 | JSON Patch Example (from RFC 6902): 172 | [ 173 | { "op": "test", "path": "/a/b/c", "value": "foo" }, 174 | { "op": "remove", "path": "/a/b/c" }, 175 | { "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] }, 176 | { "op": "replace", "path": "/a/b/c", "value": 42 }, 177 | { "op": "move", "from": "/a/b/c", "path": "/a/b/d" }, 178 | { "op": "copy", "from": "/a/b/d", "path": "/a/b/e" } 179 | ] 180 | 181 | Single operations for JSON Patch, JSON Merge Patch, and others can be crafted using -o plus -p (path) and possibly -f (from) or -v/-V (value) 182 | 183 | -o "": 184 | [JSON Patch Operations] 185 | add 186 | -o add -p "" -v "" 187 | add/replace value in object or insert value into array index (RFC 6902) 188 | replace 189 | -o replace -p "" -v "" 190 | replace value of existing object property (key) or array index (RFC 6902) 191 | remove 192 | -o remove -p "" 193 | remove specified path from the document (RFC 6902) 194 | move 195 | -o move -f "" -p "" 196 | move a path to a new or existing path/node(RFC 6902) 197 | copy 198 | -o copy -f "" -p "" 199 | copy a path to a new or existing path/node (RFC 6902) 200 | test 201 | -o test -p "" -v "" 202 | test if a path matches a value exactly (RFC 6902), return 0 if true, 1 if false 203 | 204 | [Other Operations] 205 | diff 206 | -o diff -v "" 207 | Given a value, compare with JSON text and produce a JSON Merge Patch (RFC 7396) document 208 | mergepatch 209 | -o mergepatch (-v/-V "" || -f "") [-p ] 210 | JSON Merge Patch (RFC 7396) operation: null values delete target object property 211 | Can pull data from -v/-V "" OR -f "", can merge to specific -p "" (JSONPaths allows multiple) 212 | merge 213 | -o merge (-v/-V "" || -f "") [-p ""] 214 | Non-RFC 7396 merging operation, object properties with null values are NOT removed 215 | Can pull data from -v/-V "" or -f "", can merge to specific -p "" (JSONPaths allows multiple) 216 | merge0 217 | -o merge0 (-v/-V "" || -f "") [-p ""] 218 | Merge object properties that DO NOT intersect with source JSON 219 | Can pull data from -v/-V "" or -f "", can merge to specific -p "" (JSONPaths allows multiple) 220 | merge1 221 | -o merge1 (-v/-V "" || -f "") [-p ""] 222 | Merge object properties that intersect with source JSON 223 | Can pull data from -v/-V "" or -f "", can merge to specific -p "" (JSONPaths allows multiple) 224 | 225 | -p "": 226 | -p "" the target path expressed in JSON Pointer (RFC 6901) or JSONPath 227 | 228 | -f "": 229 | copy and move require a JSON Pointer (RFC 6901) or JSONPath expression 230 | 231 | -v/-V "": 232 | -v "" is a single JSON text 233 | -V "" is a file path to a single JSON text 234 | Options for -v/-V: 235 | -s treat input as a string 236 | 237 | JSONPath Primer 238 | $ 239 | the root of the JSON document, ALL JSONPath QUERIES MUST BEGIN WITH $ 240 | .key or ['key'] 241 | a "child" operator for an object property named 'key' in a JSON object 242 | ..key or ..['key'] 243 | is a recursive operator that will find all properties named 'key' within the object 244 | ['key name'] or ["key \ud83d\udd11"] 245 | property names with spaces or escaped values MUST use bracket notation 246 | .* or [*] 247 | * returns the values of all the keys within an object or all indices in an array 248 | [start:stop:step] 249 | slice operation for arrays, accepts pos/neg integers, script and filter expressions, or leave empty 250 | [?(@.id >= 1 && @.id <= 10 )] or [?(@.key == "string" && !@['key2'])] or the off-spec [?(@name =~ /key.*/)], etc... 251 | filter expressions can return one or more matching objects within an array 252 | @ is the current object, dot and bracket notation can be used to query child nodes 253 | Use logical operators like: == (equal), != (not equal), > (greater than), < (less than), >= (greater or equal), <= (less or equal) 254 | Multiple criteria can be evaluated with && (AND) and || (OR). Regular expressions can also be used: '=~ /regexp/' 255 | You can negate a value using ! 256 | @.length is the length of an array or string 257 | @name is the current property name (an off-spec but useful quirk of the original Goessner code) 258 | [(@.length/2)] 259 | "script expression", returns a single value, use as an array index selector that allow division 260 | Note: These will NOT make it into the IETF JSONPath spec 261 | [1] or [-1] 262 | array index, integers only, positive starts at the beginning, negative references from the end 263 | ["-"] 264 | The nonexistent array member after the last array element 265 | Use with data alteration operations, will always be empty for queries of arrays 266 | Akin to /- in JSON Pointer, if used with an object simply looks for a key named "-" 267 | ["a","b"] 268 | union, a comma separated list of expressions values of multiple properties at the same level in an object 269 | Unions allow for: quoted property names (single or double), numbers, *, filter and script expressions, and slices 270 | 271 | For more examples: https://github.com/brunerd/jsonpath 272 | 273 | JSON Pointer (RFC 6901) Primer 274 | "" an empty string represents the JSON document 275 | / is the root or next child node with a property named "" an empty string (JSONPath $[""]) 276 | /key property named key in an object 277 | /1 property named 1 in an object or a numeric index in an array 278 | /- the nonexistent array member after the last array element, use with data alteration operations 279 | ~ in a property name must be escaped as ~0 280 | / in a property name must be escaped as ~1 281 | 282 | Example: /JSON pointer/does/this/1/thing/well 283 | 284 | keypath primer: 285 | This arcane summoning hails from ye olde NextStep and still used by plutil 286 | 287 | . a period is used to delimit key names, 288 | literal periods can be backslash (\) escaped 289 | key an object name or array element, there is no root character 290 | 291 | Keypath Example: this.is.1.ugly.key\.path 292 | 293 | In JSON Pointer: /this/is/1/ugly/key.path 294 | And in JSONPath: $.this.is[1].ugly.["key.path"] 295 | 296 | Note: If a keypath query begins with characters that collide with JSONPath ($), jq-style (. or [) or JSON Pointer (/) it will be evaluated as one of those. 297 | ``` 298 | 299 | ### Requirements: 300 | bash or zsh on a supported OS: 301 | * macOS 10.4+ 302 | * Linux with jsc 303 | * Windows with Linux subsystem and jsc 304 | -------------------------------------------------------------------------------- /sources/jpt.min: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | #!/bin/bash 3 | #choose your shell with the first line, works in both 4 | 5 | ############# 6 | # FUNCTIONS # 7 | ############# 8 | 9 | #BEGIN FUNCTION 10 | function jpt()( #v1.0.9 jpt([options] [query] [fileArg]) 11 | { set +x; } &> /dev/null 12 | : <<-LICENSE_BLOCK 13 | jpt - JSON Power Tool (for more info: https://github.com/brunerd/jpt) 14 | Copyright (c) 2020 Joel Bruner 15 | Other portions: Copyright (c) 2007 Stefan Goessner (goessner.net), Copyright (c) 2020 "jpaquit" (https://github.com/jpaquit), Copyright (c) 2016 Kris Nye, Copyright (c) 2012 Dharmafly 16 | Licensed under the MIT License 17 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | LICENSE_BLOCK 20 | 21 | #help text - remove to save 14k 22 | read -r -d '' helpText <<'EOT' 23 | jpt (v1.0.9) - JSON Power Tool (https://github.com/brunerd/jpt)\n\nUsage:\njpt [options] [] []\n\nArguments:\n\t[] - JSONPath, JSON Pointer, or plutil-style keypath expression (optional), returns entire document otherwise.\n\t[] - path to JSON file\n\nNotes:\n\tDefault output mode is JSON (RFC8259/STD90)\n\tMultiple JSON texts will be output as a JSON Text Sequence (RFC 7464) (use -M to change behavior and processing)\n\tjpt accepts input by file redirection, Unix pipe, here string, heredoc and via /dev/stdin (end with Control-D)\n\tjpt accepts JSON, JSON text Sequences, and non-JSON mutations such as JSON5, NDJSON and jpt's own JSONPath Object Literals\n\tJSON Text Sequences will be strictly parsed to RFC 7464 specs, non-JSON elements are only tolerated in single and concatenated JSON texts\n\tNon-JSON elements are corrected automatically, if possible, before parsing (use -c for comments via stderr with an exit status of 1)\n\t JSON5 Rehabilitations (mostly):\n\t Unquoted object keys and single quoted strings are converted to JSON strings\n\t Additional Unicode whitespaces and paragraph separators are converted to normal spaces (0x20) and newlines (0x0A)\n\t Trailing commas are removed from object and array elements\n\t Explicit plus signs on numbers are removed, decimals without leading zeroes are restored\n\t Multi-line strings with escaped line breaks are reverted to standard JSON strings\n\t Literal tabs in strings are removed also\n\t Escaped character conversions: \n\t\t \\0 to null\n\t\t \\v to '\\u000c'\n\t JSON5 number type conversions: \n\t\t NaN to null (use -8 to convert to "NaN" string)\n\t\t Inifinity to null (use -I to convert to "Infinity" string, with sign if specified)\n\t Single-line (//) and multi-line (/* */) style comments are removed\n\t\t Additionally multi-line XML () and single line Shell (#), ASM (;), and Lua (--) comments are removed\n\t\nGeneral Options:\n\t-h this help screen\n\nJSON Output Options:\n\t-i "" indent number of spaces (0-10) or use a for each level of indent\n\t-O Order property names in objects alphabetically\n\t-u Unicode escape (\\u) all characters above 0x7E\n\nAdvanced JSON Output Options:\n\t-a always output result in an array\n\t-c comment on corrections to non-standard JSON via stderr output (with exit status of 1)\n\t-F Flatten array output\n\t-I Convert JSON5 +/-Infinity value to a string with signedness (otherwise converts to null)\n\t-N Nested single element arrays are reduced\n\t-8 Convert JSON5 NaN to a string (otherwise converts to null)\n\t-/ Escape solidus / with a reverse solidus like \\/, useful for HTML with embedded JSON encoded HTML\n\nInput Options:\n\t-D Detect truncation within objects and arrays in concatenated JSON only\n\t-g path-only JSONPath Object Literals are assigned a value of null ("gratis nulls")\n\t-G Guard previously defined JSONPath Object Literals from being modified by new statements\n\t-H Help truncated JSON by closing up open strings, objects and arrays\n\t-S Treat input as a JSON string\n\nMultiple JSON Text Options:\n\t-M "" - options for working with multiple JSON texts\n\t\tS - Output JSON Text Sequences strictly conforming to RFC 7464 (default)\n\t\tN - Output newline delimited JSON texts\n\t\tC - Output concatenated JSON texts\n\t\tA - Gather JSON texts into an array, post-query and post-patching\n\t\ta - Gather JSON texts into an array, pre-query and pre-patching \n\nAlternate Output Modes (non-JSON):\n\t-l output the length of the resulting array, object property count, or length of string\n\n\t-J JSONPath path(s) of the object returned by the query\n\t-j JSONPath path(s) matched by the query results\n\n\t-R JSON Pointer path(s) of the object returned by the query\n\t-r JSON Pointer path(s) matched by the query results\n\t\tSpecifiying -EW or -Ew encodes both -r and -R JSON Pointer paths in URI fragment style\n\n\t -J and -R path output options:\n\t\t-C append the "constructor" type (Array, Object, String, Boolean, Number, or null)\n\t\t-K/-k print property (key) names and array indices only with no preceding path, default indent is 2\n\t\t\t-i "" indent spaces (0-10) or character for each level of indent\n\n\t-L JSONPath Object Literal notation output of the resulting object\n\t\tJPOL Format: =\n\t\t\t is simply Javascript expression syntax with $ as the object name\n\t\t\t\tExample: $.key, $["key"], $['key'], or $[0]\n\t\t\t is any valid JSON value (plus single quoted strings)\n\t\t\t\tExample: 'string', "string", [], {}, 42, true, false, null\n\n\t JSONPath output options for -L -J and -j:\n\t\t-d Use dot notation for object property names when possible, rather than bracket notation\n\t\t-q Use single quotes for bracketed property names, string values remain JSON double quoted\n\t\t-Q Use single quotes for BOTH bracketed property names AND string values (-L only)\n\t\t-u encode characters above 7E with \\u escape\n\n\t Output limiting options for -L, -J, and -R:\n\t\t-P Only print Primitive data types (String, Boolean, Number, null) omitting Arrays and Objects\n\t\t-Z "" Depth\n\t\t\tCombined with -L it will coalesce lower depth levels into a compound JSON object/array statement\n\t\t\tCombined with -P both -J and -R will return only purely primitive nodes at or below the Z level\n\n\t-T textual output of all data (omits property names and indices)\n\t Options:\n\t\t-e encode whitespace and escapes: \\b \\f \\n \\r \\t \\v and \\\\ (\\ escaped formats only)\n\t\t-i "" indent spaces (0-10) or character string for each level of indent\n\t\t-n convert null value to string 'null' (pre-encoding)\n\n\t\t-E "" encoding options for -T output:\n\n\t\t Encodes string characters below 0x20 and above 0x7E with pass-through for all else:\n\t\t\tx \t"\\x" prefixed hexadecimal UTF-8 strings\n\t\t\tO \t"\\nnn" style octal for UTF-8 strings\n\t\t\t0 \t"\\0nnn" style octal for UTF-8 strings\n\t\t\tu \t"\\u" prefixed Unicode for UTF-16 strings\n\t\t\tU \t"\\U "prefixed Unicode Code Point strings\n\t\t\tE \t"\\u{...}" prefixed ES2016 Unicode Code Point strings\n\t\t\tW \t"%nn" Web encoded UTF-8 string using encodeURI (respects scheme and domain of URL)\n\t\t\tw \t"%nn" Web encoded UTF-8 string using encodeURIComponent (encodes all components URL)\n\n\t\t\t -W encodes whitespace characters also\n\t\t\t -A encodes ALL characters\n\t\t\n\t\t Encodes both strings and numbers with pass-through for all else:\n\t\t\th \t"0x" prefixed lowercase hexadecimal, UTF-8 strings\n\t\t\tH \t"0x" prefixed uppercase hexadecimal, UTF-8 strings\n\t\t\to \t"0o" prefixed octal, UTF-8 strings\n\t\t\t6 \t"0b" prefixed binary, 16 bit _ spaced numbers and UTF-16 strings\n\t\t\tB \t"0b" prefixed binary, 8 bit _ spaced numbers and UTF-16 strings\n\t\t\tb \t"0b" prefixed binary, 8 bit _ spaced numbers and UTF-8 strings\n\n\t\t\t -U whitespace is left untouched (not encoded)\n\nData Processing:\n\tjpt can apply JSON Patch (RFC 6902), JSON Merge Patch (RFC 7396), and other operations to JSON text(s)\n\n\tJSON Patch processing:\n\t\t-X "" a file path to a JSON Patch array (RFC 6902)\n\t\t-x "" inline JSON Patch text (RFC 6902)\n\t\t\n\tJSON Patch Example (from RFC 6902):\n\t\t [\n\t\t\t { "op": "test", "path": "/a/b/c", "value": "foo" },\n\t\t\t { "op": "remove", "path": "/a/b/c" },\n\t\t\t { "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] },\n\t\t\t { "op": "replace", "path": "/a/b/c", "value": 42 },\n\t\t\t { "op": "move", "from": "/a/b/c", "path": "/a/b/d" },\n\t\t\t { "op": "copy", "from": "/a/b/d", "path": "/a/b/e" }\n\t\t]\n\n\tSingle operations for JSON Patch, JSON Merge Patch, and others can be crafted using -o plus -p (path) and possibly -f (from) or -v/-V (value)\n\n\t\t-o "":\n\t\t [JSON Patch Operations]\n\t\t add\n\t\t\t-o add -p "" -v ""\n\t\t\t\tadd/replace value in object or insert value into array index (RFC 6902)\n\t\t replace\n\t\t\t-o replace -p "" -v ""\n\t\t\t\treplace value of existing object property (key) or array index (RFC 6902)\n\t\t remove\n\t\t\t-o remove -p ""\n\t\t\t\tremove specified path from the document (RFC 6902)\n\t\t move\n\t\t\t-o move -f "" -p ""\n\t\t\t\tmove a path to a new or existing path/node(RFC 6902)\n\t\t copy\n\t\t\t-o copy -f "" -p ""\n\t\t\t\tcopy a path to a new or existing path/node (RFC 6902)\n\t\t test\n\t\t\t-o test -p "" -v ""\n\t\t\t\ttest if a path matches a value exactly (RFC 6902), return 0 if true, 1 if false\n\n\t\t [Other Operations]\n\t\t diff\n\t\t\t-o diff -v ""\n\t\t\t\tGiven a value, compare with JSON text and produce a JSON Merge Patch (RFC 7396) document\n\t\t mergepatch\n\t\t\t-o mergepatch (-v/-V "" || -f "") [-p ]\n\t\t\t\tJSON Merge Patch (RFC 7396) operation: null values delete target object property\n\t\t\t\tCan pull data from -v/-V "" OR -f "", can merge to specific -p "" (JSONPaths allows multiple)\n\t\t merge\n\t\t\t-o merge (-v/-V "" || -f "") [-p ""]\n\t\t\t\tNon-RFC 7396 merging operation, object properties with null values are NOT removed\n\t\t\t\tCan pull data from -v/-V "" or -f "", can merge to specific -p "" (JSONPaths allows multiple)\n\t\t merge0\n\t\t\t-o merge0 (-v/-V "" || -f "") [-p ""]\n\t\t\t\tMerge object properties that DO NOT intersect with source JSON\n\t\t\t\tCan pull data from -v/-V "" or -f "", can merge to specific -p "" (JSONPaths allows multiple)\n\t\t merge1\n\t\t\t-o merge1 (-v/-V "" || -f "") [-p ""]\n\t\t\t\tMerge object properties that intersect with source JSON\n\t\t\t\tCan pull data from -v/-V "" or -f "", can merge to specific -p "" (JSONPaths allows multiple)\n\t\t\t\t\n\t\t-p "":\n\t\t\t-p "" the target path expressed in JSON Pointer (RFC 6901) or JSONPath\n\n\t\t-f "":\n\t\t\tcopy and move require a JSON Pointer (RFC 6901) or JSONPath expression\n\n\t\t-v/-V "":\n\t\t\t-v "" is a single JSON text\n\t\t\t-V "" is a file path to a single JSON text\n\t\t Options for -v/-V:\n\t\t\t-s treat input as a string\n\t\t\t\t\nJSONPath Primer\n\t$\n\t\tthe root of the JSON document, ALL JSONPath QUERIES MUST BEGIN WITH $\n\t.key or ['key']\n\t\ta "child" operator for an object property named 'key' in a JSON object\n\t..key or ..['key']\n\t\tis a recursive operator that will find all properties named 'key' within the object\n\t['key name'] or ["key \ud83d\udd11"]\n\t\tproperty names with spaces or escaped values MUST use bracket notation\n\t.* or [*]\n\t\t* returns the values of all the keys within an object or all indices in an array\n\t[start:stop:step]\n\t\tslice operation for arrays, accepts pos/neg integers, script and filter expressions, or leave empty\n\t[?(@.id >= 1 && @.id <= 10 )] or [?(@.key == "string" && !@['key2'])] or the off-spec [?(@name =~ /key.*/)], etc...\n\t\tfilter expressions can return one or more matching objects within an array\n\t\t@ is the current object, dot and bracket notation can be used to query child nodes\n\t\tUse logical operators like: == (equal), != (not equal), > (greater than), < (less than), >= (greater or equal), <= (less or equal)\n\t\tMultiple criteria can be evaluated with && (AND) and || (OR). Regular expressions can also be used: '=~ /regexp/'\n\t\tYou can negate a value using !\n\t\t@.length is the length of an array or string\n\t\t@name is the current property name (an off-spec but useful quirk of the original Goessner code)\n\t[(@.length/2)]\n\t\t"script expression", returns a single value, use as an array index selector that allow division\n\t\tNote: These will NOT make it into the IETF JSONPath spec\n\t[1] or [-1]\n\t\tarray index, integers only, positive starts at the beginning, negative references from the end \n\t["-"]\n\t\tThe nonexistent array member after the last array element\n\t\tUse with data alteration operations, will always be empty for queries of arrays\n\t\tAkin to /- in JSON Pointer, if used with an object simply looks for a key named "-"\n\t["a","b"]\n\t\tunion, a comma separated list of expressions values of multiple properties at the same level in an object\n\t\tUnions allow for: quoted property names (single or double), numbers, *, filter and script expressions, and slices\n\n\tFor more examples: https://github.com/brunerd/jsonpath\n\t\nJSON Pointer (RFC 6901) Primer\n\t""\t\tan empty string represents the JSON document\n\t/\t\tis the root or next child node with a property named "" an empty string (JSONPath $[""])\n\t/key\t\tproperty named key in an object\n\t/1\t\tproperty named 1 in an object or a numeric index in an array\n\t/-\t\tthe nonexistent array member after the last array element, use with data alteration operations\n\t~\t\tin a property name must be escaped as ~0\n\t/\t\tin a property name must be escaped as ~1\n\n\tExample: /JSON pointer/does/this/1/thing/well\n\nkeypath primer:\n\tThis arcane summoning hails from ye olde NextStep and still used by plutil\n\t\n\t.\t\ta period is used to delimit key names, \n\t\t\t\tliteral periods can be backslash (\\) escaped\n\tkey\t\tan object name or array element, there is no root character\n\t\t\t\t\t\t\t\t\n\tKeypath Example: this.is.1.ugly.key\\.path\n\n\tIn JSON Pointer: /this/is/1/ugly/key.path\n\tAnd in JSONPath: $.this.is[1].ugly.["key.path"]\n\n\tNote: If a keypath query begins with characters that collide with JSONPath ($), jq-style (. or [) or JSON Pointer (/) it will be evaluated as one of those. 24 | EOT 25 | 26 | #JavaScript 27 | read -r -d '' JSCode <<-'EOT' 28 | var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.SIMPLE_FROUND_POLYFILL=!1;$jscomp.ISOLATE_POLYFILLS=!1;$jscomp.FORCE_POLYFILL_PROMISE=!1;$jscomp.FORCE_POLYFILL_PROMISE_WHEN_NO_UNHANDLED_REJECTION=!1;$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(a,f,e){if(a==Array.prototype||a==Object.prototype)return a;a[f]=e.value;return a};$jscomp.getGlobal=function(a){a=["object"==typeof globalThis&&globalThis,a,"object"==typeof window&&window,"object"==typeof self&&self,"object"==typeof global&&global];for(var f=0;f>>0,$jscomp.propertyToPolyfillSymbol[g]=$jscomp.IS_SYMBOL_NATIVE?$jscomp.global.Symbol(g):$jscomp.POLYFILL_PREFIX+e+"$"+g),$jscomp.defineProperty(d,$jscomp.propertyToPolyfillSymbol[g],{configurable:!0,writable:!0,value:f})))};$jscomp.polyfill("Math.sign",function(a){return a?a:function(f){f=Number(f);return 0===f||isNaN(f)?f:0>>0)+"_",d=0,g=function(r){if(this instanceof g)throw new TypeError("Symbol is not a constructor");return new f(e+(r||"")+"_"+d++,r)};return g},"es6","es3");$jscomp.polyfill("Symbol.iterator",function(a){if(a)return a;a=Symbol("Symbol.iterator");for(var f="Array Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array".split(" "),e=0;eq?Math.max(-1===Math.sign(c)?-1:0,q+n):Math.min(n,q);h=0>h?Math.max(-1===Math.sign(c)?-1:0,h+n):Math.min(n,h);for(g=-1===Math.sign(c)?">":"<";eval(q+g+h);q+=c)n=r.slice(),n.unshift(q),d.trace(n,p,m)}},eval:function(g,_v,_vname){r=g.slice().split("").reverse().join("").replace(/(["'])(.*?)\1(?!\\)/g,"").replace(/(\/.*?\/(?!\\)\s*~=)|(=~*\s\/.*?\/(?!\\))/g,"").replace(/\(\s*/g,"(").replace(/([;\.\+\-~!\*\/%><&\^\|:\?,])/g," ").replace(/\s+/g," ").split("").reverse().join("").split(" ").filter(function(m){return/\(/.test(m)}).filter(function(m){return/[!^]\(|[\w\d_$]\(/.test(m)}).filter(function(m){return!/test\(|exec\(|match\(/.test(m)});if(r.length)throw Error("Invocation violation: "+r);try{return eval(g.replace(/(^|[^\\])@/g,"$1_v").replace(/\\@/g,"@").replace(/(_v(?:(?!(\|\||&&)).)*)=~((?:(?!\)* *(\|\||&&)).)*)/g,function(m,c,n,q,h,b){return m?q.trim()+".test("+c.trim()+")":m}).replace(/((?:(?!\)* *(\|\||&&)).)*)\s+=~\s+(_v(?:(?!(\|\||&&)).)*)/g,function(m,c,n,q,h,b){return m?c.trim()+".test("+q.trim()+")":m}))}catch(m){throw new SyntaxError("eval: "+m.message+": "+g.replace(/(^|[^\\])@/g,"$1_v").replace(/\\@/g,"@").replace(/(_v(?:(?!(\|\||&&)).)*)=~((?:(?!\)* *(\|\||&&)).)*)/g,function(c,n,q,h,b,l){return c?h.trim()+".test("+n.trim()+")":c}).replace(/((?:(?!\)* *(\|\||&&)).)*)\s+=~\s+(_v(?:(?!(\|\||&&)).)*)/g,function(c,n,q,h,b,l){return c?h.trim()+".test("+n.trim()+")":c}));}}};if(f&&void 0!==a&&("VALUE"==d.resultType||/^PATH/.test(d.resultType)))return d.trace(d.normalize(f),a,[]),d.result.length?d.result:[]}function jscChunkPrint(a){var f=0,e=a.length,d='\n "," ", ," },{ ":" ":{'.split(" ");do{if(f+maxSize.print>e)var g=e;else{for(var r=0;r<=d.length-1;r++){var p=a.lastIndexOf(d[r],f+maxSize.print);if(-1!==p&&p>f){g=p+d[r].length-1;break}}pe.maxDepth?-1:e.maxDepth;var g=e.q?"'":'"',r=e.Q?"'":'"',p=[],m="",c=function(x,A){var B="";if(x.constructor===Number)for(var z=0;zv?/[\s|\b|\\]/.test(a[c])&&(/^\\/.test(t)||e.e)&&!e.A?/^\\/.test(t)&&"\\"==a[c]?l.push("\\\\"):e.e?l.push(a[c].replace(/[\s|\b|\\]/g,function(x){switch(x){case "\\":return"\\\\";case " ":return" ";case "\b":return"\\b";case "\f":return"\\f";case "\n":return"\\n";case "\r":return"\\r";case "\t":return"\\t";case "\v":return"\\v"}})):e.W?(v=t+n+(q+v.toString(u)).slice(b)+h,l.push(v+k)):l.push(a[c]):e.encoding.b||e.encoding.B||e.encoding["6"]||e.encoding.o||e.encoding.h||e.encoding.H||e.encoding.w||e.encoding.W||(e.encoding.U||e.encoding.E||e.encoding.O||e.encoding["0"]||e.encoding.u||e.encoding.x)&&(y.test(a[c])||e.A)?/[\s|\b]/.test(a[c])&&e.U?l.push(a[c]):(v=t+n+(q+v.toString(u)).slice(b)+h,l.push((e.encoding.B?v.slice(0,8)+"_"+v.slice(8):v)+k)):l.push(a[c]):e.encoding?16===w?(v=(q+v.toString(u)).slice(b),l.push(t+(e.encoding.B?v.slice(0,8)+"_"+v.slice(8):v)+k)):e.encoding.U||e.encoding.E?55296>v||57344<=v?l.push(t,n,(q+v.toString(16)).slice(b),h):(c++,l.push(t,n,(q+(1024*(v-55296)+a.charCodeAt(c)-56320+65536).toString(16)).slice(b),h)):2048>v?l.push(t,(192|v>>6).toString(u),k,t,(128|v&63).toString(u),k):55296>v||57344<=v?l.push(t,(224|v>>12).toString(u),k,t,(128|v>>6&63).toString(u),k,t,(128|v&63).toString(u),k):(c++,v=65536+((v&1023)<<10|a.charCodeAt(c)&1023),l.push(t,(240|v>>18).toString(u),k,t,(128|v>>12&63).toString(u),k,t,(128|v>>6&63).toString(u),k,t,(128|v&63).toString(u),k)):l.push(a[c])}a=l.join("");e.encoding.H&&(a=a.toUpperCase())}else if(a.constructor===Number)if(-1===Math.sign(a)?(b="-",a*=-1):b="",Infinity===a)a=e.I?b+"Infinity":e.n?"null":"";else if(e.encoding.b||e.encoding.B||e.encoding["6"]){a=Math.floor(a).toString(2);e.encoding.b?l=k=8:e.encoding.B?(k=16,l=8):e.encoding["6"]&&(l=k=16);t=a.length+(a.lengtha?"0":"")+(e.encoding.h?Math.floor(a).toString(16):Math.floor(a).toString(16).toUpperCase())):e.encoding.o?a=b+"0o"+Math.floor(a).toString(8):e.encoding.O&&(a=b+"0"+Math.floor(a).toString(8));p=[m+a]}else e.R||e.J?p=[m+f+(e.C?c:"")]:"string"!==typeof a||n?p=[f+"="+a]:(a=a.replace(e.u?/[\u0000-\u001f\u007f-\uffff|\\|"|']/g:/[\u0000-\u001f\u007f|\\|"|']/g,function(x){switch(x){case "\b":return"\\b";case "\f":return"\\f";case "\n":return"\\n";case "\r":return"\\r";case "\t":return"\\t";case "\\":return"\\\\";case '"':return"'"===r?'"':'\\"';case "'":return"'"===r?"\\'":"'";default:return"\\u"+("0000"+x.charCodeAt(0).toString(16)).slice(-4)}}),p=[f+"="+r+a+r]);return p.flat()}function objectifyExpressions(a,f){function e(d){d=d.split("");for(var g=!1,r=!1,p=!1,m=!1,c=!1,n=!1,q,h=!1,b=0,l=[],k=0;k"===d[k]||"="===d[k])&&"="===d[k+1])q=void 0,k+=1,h=!0;else if("<"===d[k]||">"===d[k])q=void 0,h=!0;else if("="===d[k]&&"~"===d[k+1])q=void 0,h=!0,k+=1;else if("&"===d[k]&&"&"===d[k+1]||"|"===d[k]&&"|"===d[k+1]){if(1!=h&&void 0!==q&&(d.splice(q+1,0,"!==undefined"),k++),h=!1,b)for(var t=0;t|~=))/g,function(z){return z.replace(/./g," ")});var c=/=/g;p=[];var n=0,q=[];do{q=c.exec(m);if(null===q||0===c.lastIndex||n===c.lastIndex)break;n=c.lastIndex;p.unshift(n)}while(0!==c.lastIndex&&c.lastIndex!==m.length);if(f.disallowData&&p.length)throw new SyntaxError("Data assignment (=) not allowed in path specification");if(1a)||+a});(function(a,f){"object"===typeof exports?f(module.exports):"function"===typeof define&&define.amd?define(["exports"],f):(a.jsonpatch={},a.returnExports=f(a.jsonpatch))})(this,function(a){function f(h){Error.call(this,h);this.message=h}function e(h){Error.call(this,h);this.message=h}function d(h){var b;if(n(h))return h.slice();if(null===h)return h;if("object"===typeof h){var l={};for(b in h)Object.hasOwnProperty.call(h,b)&&(l[b]=h[b]);return l}return h}function g(h,b){var l;if(h===b)return!0;if(typeof h!==typeof b)return!1;if("object"===typeof h){var k=n(h),t=n(b);if(k!==t)return!1;if(k){if(h.length!=b.length)return!1;for(l=0;lk.length)throw new RangeError("Array index '"+t+"' does not exist. Use '-' to add to the end.");k.splice(t,0,b)}else k[t]=b;return k},l)};c.prototype.remove=function(h,b){return 0===this.length?[]:this._action(h,function(l,k){if(!Object.hasOwnProperty.call(l,k))throw new e("Remove operation must point to an existing value!");n(l)?l.splice(k,1):delete l[k];return l},b)};c.prototype.replace=function(h,b,l){return 0===this.length?b:this._action(h,function(k,t){if(null===k)throw Error("Unable to replace to null!");if(!Object.hasOwnProperty.call(k,t))throw new RangeError("Replace requires an existing location. Property '"+t+"' not found.");n(k)?k.splice(t,1,b):k[t]=b;return k},l)};c.prototype.get=function(h){var b;if(0===this.length)return h;this._action(h,function(l,k){if(!Object.hasOwnProperty.call(l,k))throw new e("Path not found in document");b=l[k];return l},!0);return b};c.prototype.subsetOf=function(h){if(this.length<=h.length)return!1;for(var b=0;b"===a[b+2]?(a[b]="",a[b+1]="",a[b+2]="",b+=2,r=!1):a[b]="";else if(/[\s\ufefe]/.test(a[b])){option.c&&!/[ \n\r\t]/g.test(a[b])&&option.c&&printErr("Byte "+(b+1)+": additional whitespace character +("+JSON.stringify(a[b],null,0)+") (JSON5)");/[\f\r\v\u2028\u2029]/g.test(a[b])?"\r"===a[b]&&"\n"===a[b+1]?b+=1:a[b]="\n":/[^ \n]/g.test(a[b])&&(a[b]=" ");if(void 0===h){m=b+1;continue}if(!c.length&&void 0!==h||b===l-1)n=!0}else if('"'===a[b]||"'"===a[b])'"'===a[b]?f=!0:(e=!0,a[b]='"',option.c&&printErr("Byte "+(b+1)+": single quoted string (JSON5)")),c.length&&(c.length&&"Object"===c[0].type?"OBJECT_BEGIN"===c[0].state||"NEEDS_PROPNAME"===c[0].state?c[0].state="NEEDS_NAMESEP":"NEEDS_VALUE"===c[0].state&&(c[0].state="NEEDS_ENDER"):!c.length||"Array"!==c[0].type||"ARRAY_BEGIN"!==c[0].state&&"NEEDS_VALUE"!==c[0].state||(c[0].state="NEEDS_ENDER")),h=b;else if(":"===a[b])c.length&&"Object"===c[0].type&&"NEEDS_NAMESEP"===c[0].state&&(c[0].state="NEEDS_VALUE"),h=b;else if("{"===a[b])option.D&&c.length&&("\n"===a[b-1]||"NEEDS_VALUE"!==c[0].state&&"ARRAY_BEGIN"!==c[0].state)?(--b,option.c&&printErr("Byte "+(b+1)+": Truncation Detected"),n=!0):(c.length&&"Object"===c[0].type&&"NEEDS_VALUE"===c[0].state?c[0].state="NEEDS_ENDER":!c.length||"Array"!==c[0].type||"ARRAY_BEGIN"!==c[0].state&&"NEEDS_VALUE"!==c[0].state||(c[0].state="NEEDS_ENDER"),c.unshift({type:"Object",state:"OBJECT_BEGIN"}),h=b);else if("["===a[b])option.D&&c.length&&("\n"===a[b-1]||"NEEDS_VALUE"!==c[0].state&&"ARRAY_BEGIN"!==c[0].state)?(--b,option.c&&printErr("Byte "+(b+1)+": Truncation Detected"),n=!0):(c.length&&"Object"===c[0].type&&"NEEDS_VALUE"===c[0].state?c[0].state="NEEDS_ENDER":!c.length||"Array"!==c[0].type||"ARRAY_BEGIN"!==c[0].state&&"NEEDS_VALUE"!==c[0].state||(c[0].state="NEEDS_ENDER"),c.unshift({type:"Array",state:"ARRAY_BEGIN"}),h=b);else if("}"===a[b])","===a[h]&&(option.c&&printErr("Byte "+(h-1)+": trailing comma (JSON5)"),a[h]=""),c.shift(),c.length?h=b:n=!0;else if("]"===a[b])","===a[h]&&(option.c&&printErr("Byte "+(h-1)+": trailing comma (JSON5)"),a[h]=""),c.shift(),c.length?h=b:n=!0;else if(","===a[b])h=b,c.length&&"Object"===c[0].type&&"NEEDS_ENDER"===c[0].state?c[0].state="NEEDS_PROPNAME":c.length&&"Array"===c[0].type&&"NEEDS_ENDER"===c[0].state&&(c[0].state="NEEDS_VALUE");else if("n"===a[b]&&"u"===a[b+1]&&"l"===a[b+2]&&"l"===a[b+3]||"t"===a[b]&&"r"===a[b+1]&&"u"===a[b+2]&&"e"===a[b+3]||"f"===a[b]&&"a"===a[b+1]&&"l"===a[b+2]&&"s"===a[b+3]||"e"===a[b+4]){c.length&&"Object"===c[0].type&&"NEEDS_VALUE"===c[0].state?c[0].state="NEEDS_ENDER":!c.length||"Array"!==c[0].type||"ARRAY_BEGIN"!==c[0].state&&"NEEDS_VALUE"!==c[0].state||(c[0].state="NEEDS_ENDER");var k=a.slice(b,b+5).join("");if("true"===k.slice(b,b+4)||"true"===k.slice(b,b+4))h=b+4;"false"===k.slice(b,b+5)&&(h=b+5)}else if("+"===a[b]&&(/\d/.test(a[b+1])||"."===a[b+1]))option.c&&printErr("Byte "+(b+1)+": explicit plus + for value (JSON5)"),c.length&&"Object"===c[0].type&&"NEEDS_VALUE"===c[0].state?c[0].state="NEEDS_ENDER":!c.length||"Array"!==c[0].type||"ARRAY_BEGIN"!==c[0].state&&"NEEDS_VALUE"!==c[0].state||(c[0].state="NEEDS_ENDER"),a[b]="";else if("."===a[b]&&!/\d/.test(a[b-1]))option.c&&printErr("Byte "+(b+1)+": decimal point wihtout preceding digit (JSON5)"),c.length&&"Object"===c[0].type&&"NEEDS_VALUE"===c[0].state?c[0].state="NEEDS_ENDER":!c.length||"Array"!==c[0].type||"ARRAY_BEGIN"!==c[0].state&&"NEEDS_VALUE"!==c[0].state||(c[0].state="NEEDS_ENDER"),a[b]="0.",h=b;else if("."===a[b]&&!/\d/.test(a[b+1]))option.c&&printErr("Byte "+(b+1)+": trailing decimal lacking mantissa (JSON5)"),a[b]="";else if("N"===a[b]&&"a"===a[b+1]&&"N"===a[b+2]&&(!c.length||"Object"===c[0].type&&"{"!==a[h]&&","!==a[h]||"Array"===c[0].type))option.c&&printErr("Byte "+(b+1)+": NaN for value (JSON5)"),option["8"]?(a[b]='"',a[b+1]="NaN",a[b+2]='"'):(a[b]="",a[b+1]="",a[b+2]="null"),h=b+=2;else if("-"!==a[b]&&"+"!==a[b]||"I"!==a[b+1]||"n"!==a[b+2]||"f"!==a[b+3]||"i"!==a[b+4]||"n"!==a[b+5]||"i"!==a[b+6]||"t"!==a[b+7]||"y"!==a[b+8])if("I"===a[b]&&"n"===a[b+1]&&"f"===a[b+2]&&"i"===a[b+3]&&"n"===a[b+4]&&"i"===a[b+5]&&"t"===a[b+6]&&"y"===a[b+7])option.c&&printErr("Byte "+(b+1)+": Infinity as value (JSON5)"),a[b]="",a[b+1]="",a[b+2]="",a[b+3]="",a[b+4]="",option.I?(a[b+5]='"',a[b+6]="Infinity",a[b+7]='"'):(a[b+5]="",a[b+6]="",a[b+7]="null"),b+=4;else if("0"!==a[b]||"x"!==a[b+1]||c.length&&"Array"!==c[0].type&&("Object"!==c[0].type||":"!==a[h]))if("-"===a[b]||/\d/.test(a[b]))c.length&&"Object"===c[0].type&&"NEEDS_VALUE"===c[0].state?c[0].state="NEEDS_ENDER":!c.length||"Array"!==c[0].type||"ARRAY_BEGIN"!==c[0].state&&"NEEDS_VALUE"!==c[0].state||(c[0].state="NEEDS_ENDER"),/\d/.test(a[b])&&(h=b);else if(/[$_A-Za-z]/.test(a[b])&&c.length&&"Object"===c[0].type&&("{"===a[h]||","===a[h])){option.c&&printErr("Byte "+(b+1)+": unquoted object key name (JSON5)");a[b]='"'+a[b];for(b+=1;bmaxSize.print)jscChunkPrint(possibleRS+resultText);else try{print(possibleRS+resultText)}catch(a){printErr("print "+a)}}; 29 | EOT 30 | 31 | #shell script 32 | locations=( "/System/Library/Frameworks/JavaScriptCore.framework/Versions/Current/Helpers/jsc" "/System/Library/Frameworks/JavaScriptCore.framework/Versions/Current/Resources/jsc" );for loc in ${locations[@]}; do [ -x "${loc}" ] && jsc="${loc}" && break; done;[ -z "${jsc}" ] && jsc=$(which jsc);if [ -z "${jsc}" ]; then locations=( "/System/Library/Frameworks/JavaScriptCore.framework/Versions/Current" "/usr/bin/jsc" "/usr/libexec/webkit2gtk*" );for loc in ${locations[@]}; do jsc=$(find -L "${loc}" -name 'jsc' -maxdepth 2 2>/dev/null);[ -n "${jsc}" ] && break;done;fi;[ -z "${jsc}" ] && echo "Unable to locate a jsc binary!" && exit 1;[ -n "${BASH_VERSION}" ] && local OPTIND OPTARG; declare options;while getopts ":8cKkDSQPAE:Ff:lNLOuo:i:aCIeHhdnqgGJzjsRrTtUWwZ:v:V:x:X:p:M:%/" option; do case "${option}" in 'J'|'L'|'R'|'t'|'j'|'l'|'r'|'t') [ -z "${outputOpt}" ] && outputOpt="${option}" ;;'o')[ -z "${alterOp}" ] && { options+="${option}"; alterOp="${OPTARG}"; } ;;'p')[ -z "${pathArg}" ] && { options+="${option}"; pathArg="${OPTARG}"; } ;;'v'|'V')[ -z "${valueArg}" ] && { options+="${option}"; valueArg="${OPTARG}"; } ;;'f')[ -z "${fromArg}" ] && { options+="${option}"; fromArg="${OPTARG}"; } ;;'x'|'X')[ -z "${JSONPatchArg}" ] && { options+="${option}"; JSONPatchArg="${OPTARG}"; } ;;'i')options+="${option}"; spaceArg="${OPTARG}";;'M')options+="${option}"; multiOutArg="${OPTARG}";;'Z')depthArg="${OPTARG}";;'E')[ -z "${encodingArg}" ] && encodingArg+="${OPTARG/\%/W}";;'h')echo -e "${helpText}" | less; exit;;'?'):;;*)options+="${option}";;esac;done;options+="${outputOpt}";[ $OPTIND -ge 2 ] && shift $((OPTIND-1));queryArg="${1}";fileArg="${2}";[ -f "${queryArg}" ] && [ -z "${fileArg}" ] && { fileArg="${queryArg}"; unset queryArg; };readFileSupport="$(${jsc} -e 'print(typeof readFile === "function")')";if [ -n "${fileArg}" ]; then if [ "${fileArg}" != '/dev/stdin' ] && ! [ -f "${fileArg}" ]; then echo "--> File not found: ${fileArg}" >&2;return 1;elif ! [ -r "${fileArg}" ]; then echo "--> File not readable: ${fileArg}" >&2;return 1;fi;if [ "${readFileSupport}" = "true" ]; then if stat -f %z . &> /dev/null; then fileSize=$(stat -f %z "${fileArg}");elif stat -c %s . &> /dev/null; then fileSize=$(stat -c %s "${fileArg}");elif stat --format %s . &> /dev/null; then fileSize=$(stat --format %s "${fileArg}");fi;if [ "${fileSize}" -ge 2147483648 ]; then echo "--> File exceeds readFile() maximum size (2GiB)!" >&2;return 1;fi;fi;fi;if [ "${readFileSupport}" = "false" ]; then { errOut=$( { { "${jsc}" -e "${JSCode}" -- "${queryArg}" "" "${options}" "${spaceArg}" "${valueArg}" "${pathArg}" "${depthArg}" "${encodingArg}" "${alterOp}" "${fromArg}" "${JSONPatchArg}" "${multiOutArg}" <<< "$(sed '/^$/d' "${fileArg:-/dev/stdin}")" ; } 1>&3 ; } 2>&1); } 3>&1;elif [ -f "${fileArg:=/dev/stdin}" ]; then { errOut=$( { { "${jsc}" -e "${JSCode}" -- "${queryArg}" "${fileArg}" "${options}" "${spaceArg}" "${valueArg}" "${pathArg}" "${depthArg}" "${encodingArg}" "${alterOp}" "${fromArg}" "${JSONPatchArg}" "${multiOutArg}"; } 1>&3 ; } 2>&1); } 3>&1;else [ -t '0' ] && echo -e "$(echo -e "${helpText}" | head -n 1)\nUsage: jpt [options] [query] [filepath] (see jpt -h for more help...)" >/dev/stderr && exit 0; { errOut=$( { { "${jsc}" -e "${JSCode}" -- "${queryArg}" "/dev/stdin" "${options}" "${spaceArg}" "${valueArg}" "${pathArg}" "${depthArg}" "${encodingArg}" "${alterOp}" "${fromArg}" "${JSONPatchArg}" "${multiOutArg}" <<< "$(cat)"; } 1>&3 ; } 2>&1); } 3>&1;fi;if [ -n "$(sed -e '/^--> Debug:/d' <<< "${errOut}")" ]; then /bin/echo "$errOut" >&2; return 1; fi 33 | ) 34 | #END FUNCTION 35 | 36 | jpt "$@" 37 | exit $? 38 | --------------------------------------------------------------------------------