Reputation: 93
I have an existing json which have a from like this:
{
"arg1": "Admin",
"arg2": 0,
"data": [
{
"arg3": "11",
"user": "user1",
"age": 51,
"arg4": "11"
},
{
"arg3": "22",
"user": "user2",
"age": 52,
"arg4": "22"
},
{
"arg3": "33",
"user": "user3",
"age": 53,
"arg4": "33"
},
{
"arg3": "44",
"user": "user4",
"age": 54,
"arg4": "44"
}
]
}
Then I try this command:
$ cat tmp.json|jq '.data|.[]|{user,age}'
{
"user": "user1",
"age": 51,
}
{
"user": "user2",
"age": 52,
}
{
"user": "user3",
"age": 53,
}
{
"user": "user4",
"age": 54,
}
What I expect to output is:
{
"department": "Admin",
"user_age": {
"user1": "51",
"user2": "52",
"user3": "53",
"user4": "54"
},
"year": 2016
}
In jq's manual, my request is close to example 23.
So I tried to use from_entries
function
cat tmp.json|jq '.data|.[]|{user,age}|from_entries'
but get this error:
jq: error (at :30): Cannot index string with string "key"
I know this is because of its format not equal an entry.
So, what should I do to convert to the expected output?
Upvotes: 0
Views: 1085
Reputation: 14625
As Jeff explained, from_entries expects input of the form
[ {key:xxx, value:yyy} ]
so Hao's filter
.data | .[] | {user,age} | from_entries
requires two small modifications to generate the desired user_age
object:
{key,value}
objectse.g.
.data | [.[]|{key:user, value:age|tostring}] | from_entries
(we include tostring
because the values in the example output are strings)
But since [ .[]| ... ]
is the same as map(...)
this could be written
.data | map({key:user, value:age|tostring}) | from_entries
Here is a complete solution:
{
"department": .arg1,
"user_age": .data | map({key:.user, value:.age|tostring}) | from_entries,
"year": 2016
}
Sample output
{
"department": "Admin",
"user_age": {
"user1": "51",
"user2": "52",
"user3": "53",
"user4": "54"
},
"year": 2016
}
Upvotes: 0
Reputation: 189
you can also try:
cat tmp.json|jq '{department: .arg1, user_age: (.data|map({(.user): .age})|add), year: 2016}'
or
cat tmp.json|jq '{department: .arg1, user_age: .data|map({(.user): .age})|add, year: 2016}'
Upvotes: 1
Reputation: 134811
from_entries
expects an array of objects with key
and value
properties. You are however generating separate objects with user
and age
properties which just would not work. First of all, you would need to make sure that the properties are in an array, then have the separate key/value pairs for each of the values you want in the array.
With that said, you don't really need to use entries to build out the result, it's not the right tool for the job. You just want to pull some properties from each of the data objects and add to another object mapping users to ages. There's many ways this can be achieved, I would use reduce
to accomplish this.
reduce .data[] as $d ({}; .[$d.user] = $d.age)
To get your final result, just combine the parts you need into the object you're requiring. I'm not sure where you got that 2016 from, I'm assuming it's just hardcoded.
{department: .arg1, user_age: (reduce .data[] as $d ({}; .[$d.user] = $d.age)), year: 2016}
Upvotes: 1