Reputation: 5271
I'm trying to use jq
to parse JSON that looks something like:
{
"username": "billy",
"hero": {
"something": "goeshere"
},
"bumper": {
"bumper2": {
"bumper3": "splodge"
}
},
"morgan": [{
"abc": 123
}, 2, 4, {
"def": 567
}],
"password": "issilly"
}
into
request.username == 'billy' && request.hero.something == 'goeshere' && request.bumper.bumper2.bumper3 == 'splodge' && request.morgan[0].abc == 123 && request.morgan[1] == 2 && request.morgan[2] == 4 && request.morgan[3].def == 567 && request.password == 'issilly'
So far I've got to
jq '. | to_entries[] | "request.\(.key) == '\(.value)'"'
which gets me part of the way there, but I can't work out how to "walk down" into the deep-nested elements, nor how to join the strings produced into a single line delimited with ' && '
Upvotes: 2
Views: 225
Reputation: 50750
paths(scalars)
outputs arrays representing paths to strings and numbers in .
, and using getpath
you can get values at those paths. So all you need is a function that converts path representations to path expressions, like:
def pr2pe:
reduce .[] as $n ([];
if $n|type == "string"
then . + [$n]
elif $n|type == "number" and length
then .[-1] += "[\($n)]"
else error("invalid path representation")
end) | join(".");
[ paths(scalars) as $p
| "\($p | pr2pe) == \(getpath($p) | tojson)" ]
| join(" && ")
See it on jqplay
Upvotes: 4
Reputation: 198294
This will give you output that is not quite what you posted, but should be good enough, given that JavaScript does not distinguish foo.bar
and foo["bar"]
.
jq -r '
. as $data |
[path(.. |
select(type != "object" and type != "array")
)] |
map(
. as $path |
map("[" + (. | tojson) + "]") |
join("") |
"request\(.) = \($data | getpath($path) | tojson)"
) |
join(" && ")
' < test.json
Output:
request["username"] = "billy" &&
request["hero"]["something"] = "goeshere" &&
request["bumper"]["bumper2"]["bumper3"] = "splodge" &&
request["morgan"][0]["abc"] = 123 &&
request["morgan"][1] = 2 &&
request["morgan"][2] = 4 &&
request["morgan"][3]["def"] = 567 &&
request["password"] = "issilly"
Explanation: ..
gives us all values; but we want only the leaf values, so we filter out those that are arrays or objects. Then we get the array of paths using [path()]
: this will be an array of arrays of path steps, like this: [["username"], ["hero", "something"], ["bumper", "bumper2", "bumper3"], ["morgan", 0, "abc"]... ]
etc. Now for each path, we need to enclose each path step in brackets to get something that JavaScript can understand. tojson
will give the exact thing that the brackets need, so that string keys of objects get quoted but the integral keys of arrays don't. We can now put together the equality expression: the left side needs a request
prepended to the brackety path we constructed, while we can use getpath
to get the value that should be on the right hand side (again using tojson
to get the correct literal).
Upvotes: 2