3 ms·
> the learning investment required by jq (learning a full blown DSL) is total overkill for most simple JSON based tasks. There's no reason why you would need t
by jolmg 7y ago
> the learning investment required by jq (learning a full blown DSL) is total overkill for most simple JSON based tasks.
There's no reason why you would need to learn the whole DSL for simple tasks. Just learn what you need. For simple stuff, the DSL is also simple.
jtc also seems to have its own DSL by the way, and it doesn't really seem more intuitive than jq's:
jtc -x'[0][:][name]<person>v [-1][children]<kids:false>f[0]<kids:true>v' -T'{"{person} has children":{kids}}' -r
That's apparently the equivalent of:
jq '.Directory | map({"\(.name) has children": (.children | length == 0)}) | .[]'
There are some things that seem simpler on jtc, though, like searches of string values without regard to the json structure.
- zeroimpl 7y agoI’d really like a CLI tool which solves this problem using a syntax I already know. I struggle with jq because I use it quite infrequently. IMO the ideal solution is something using pure JavaScript syntax, possibly with a library resembling jQuery for tree traversal.
- jolmg 7y agoMost of jq's syntax is just a mix of JavaScript and a typical shell's. Every expression has an input and output like a shell command's stdin and stdout. Functions work on arguments and their stdin to produce their stdout. Here's an explanation of the syntax in the command I posted: jq ' # output the value at "Directory" from input object .Directory # pipe to map (JavaScript also has map()). The argument of map works in # the context of each element in map's input array. | map( # Produce an object where the property name is a string that # interpolates the value of the "name" property of this element. # Instead of interpolating, we could have also used this more # JavaScript-ish (ES5) syntax: # # {(.name + " has children"): ... # # The property value is an expression that gets the value of the # "children" property and pipes it to the expression `length != 0`. # `length` (which JavaScript also has) outputs the length of the # piped input, and then we compare that with 0. {"\(.name) has children": (.children | length != 0)} ) # map's output is a single record which is an array. We pipe that to # .[] to make multiple records, each an element of the array. The # syntax here is comprised of 2 parts: `.`, which is the input object, # and `[]` which is the subscript syntax without an index. | .[] ' > IMO the ideal solution is something using pure JavaScript syntax The greatest advantage of the current syntax is the great balance it has between legibility and terseness. I don't think making it pure JavaScript would be better. > possibly with a library resembling jQuery for tree traversal Using jQuery in JavaScript to traverse JavaScript objects? I don't know what to say...
- zeroimpl 7y agoSomething like this would do the same, if somebody implemented a tool called jsed: jsed ' Object.fromEntries( $("Directory").map( x => [ x.name + " has children", x.children && x.children.length != 0 ] ) )' Interestingly enough there is already a tool called jsed which seems to kind of do this... https://www.npmjs.com/package/jsed https://www.npmjs.com/package/jsed Edit: Note the jQuery part of it is for advanced cases like searching for specific nodes in the tree, then navigating back up to the parent. Basically the cases like "<Work>[-1][children]" from the jtc guide, I would write as: '$("Work").parent().find("children")'
- jolmg 7y agoThat was supposed to be a `!=` instead of a `==`. jq '.Directory | map({"\(.name) has children": (.children | length != 0)}) | .[]'