I’m trying to generate a new json from an existing one. In the new json is an array with one entry, which needs to remain the first entry in the array. With jq generate additional entries to this arrays. But my code replaces the existing entry. I’ve created a smaller representation of my Problem.
This following code is what I have so far.
echo '{"Results": [{"Input": [{"foo":" bar", "this": "that"}, {"foo": "bing"}]}]}' |
jq '{"sections": [{"first": "element", "that": "is needed at pos 0 in this array"}, .Results[] | .Input[]? | {"markdown": true, "facts":[{name: "MyFoo", value: .foo}]}]}'
This is the result i, which is missing the first element of the sections list.
{
"sections": [
{
"markdown": true,
"facts": [
{
"name": "MyFoo",
"value": " bar"
}
]
},
{
"markdown": true,
"facts": [
{
"name": "MyFoo",
"value": "bing"
}
]
}
]
}
My desired result would be the following:
{
"sections": [
{
"first": "element",
"that": "is needed at pos 0 in this array"
},
{
"markdown": true,
"facts": [
{
"name": "MyFoo",
"value": " bar"
}
]
},
{
"markdown": true,
"facts": [
{
"name": "MyFoo",
"value": "bing"
}
]
}
]
}
I’v tried to use two linked jq command but his destroys the order in the sections list.
echo '{"Results": [{"Input": [{"foo":" bar", "this": "that"}, {"foo": "bing"}]}]}' |
jq '{"sections": [ .Results[] | .Input[]? | {"markdown": true, "facts":[{name: "MyFoo", value: .foo}]}]}' |
jq '.sections += [{"first": "element", "that": "is needed at pos 0 in this array"}]'
2
Answers
Something like this?
In particular, note the use of
+
to concatenate two arrays.You are almost there.
Let’s format your attempt a bit, to understand what it does:
I formatted it according to your intent: you want an object whose
sections
property is an array that has the object{ "first": "element" ... }
as its first item and the other items are computed from the properties.Results.Input
of the input object.Unfortunately, the documentation of
jq
does not specify the precedence of its operators. While everybody (including me) assumes that the pipe operator (|
) has higher precedence than the comma operator (,
) (an assumption probably based on how these operators work in the languages inspired from C), injq
is the other way around:,
has higher precedence than|
.This makes your code work equivalent to this:
The first filter (
{"first": ... }, .Results[]
) produces:The next filter,
.Input[]
discards the object{first: "element" ...}
and its output is[{"foo": " bar","this": "that"}, {"foo": "bing"}]
and now it is clear why the output of the entire program is not the one that you expect.The solution is simple: wrap the pipeline that processes the input in parentheses and it will work.
Given that
jq
language is not JSON (but it includes JSON), you don’t have to wrap the keys in quotes. Getting rid of the quotes around keys and wrapping the program on multiple lines makes it easier to read:Check it online on the
jq
playground.