Reputation: 21
I have a json file like this :
{"users":{"347793":"user1"}}
{"users":{"6560536":"user2"}}
{"users":{"6637901":"user3"}}
{"users":{"5850517":"user4"}}
{"users":{"2907509":"user5"}}
{"users":{"6611743":"user6"}}
{"users":{"6535592":"user7"}}
{"users":{"5586286":"user8"}}
{"users":{"2484439":"user9"}}
{"messages":{"id":"id1","owner":{"id":"347793","type":"user"},"otherUser":{"id":"6560536","type":"user"}}}
{"messages":{"id":"id2","owner":{"id":"6637901","type":"user"},"otherUser":{"id":"6560536","type":"user"}}}
{"messages":{"id":"id3","owner":{"id":"2907509","type":"user"},"otherUser":{"id":"2484439","type":"user"}}}
{"messages":{"id":"id4","owner":{"id":"347793","type":"user"},"otherUser":{"id":"2907509","type":"user"}}}
{"messages":{"id":"id5","owner":{"id":"5850517","type":"user"},"otherUser":{"id":"5850517","type":"user"}}}
{"messages":{"id":"id6","owner":{"id":"5586286","type":"user"},"otherUser":{"id":"347793","type":"user"}}}
I want to get the output file like this, to change the owner's type to the user's name:
{"users":{"347793":"user1"}}
{"users":{"6560536":"user2"}}
{"users":{"6637901":"user3"}}
{"users":{"5850517":"user4"}}
{"users":{"2907509":"user5"}}
{"users":{"6611743":"user6"}}
{"users":{"6535592":"user7"}}
{"users":{"5586286":"user8"}}
{"users":{"2484439":"user9"}}
{"messages":{"id":"id1","owner":{"id":"347793","type":"user1"},"otherUser":{"id":"6560536","type":"user2"}}}
{"messages":{"id":"id2","owner":{"id":"6637901","type":"user3"},"otherUser":{"id":"6560536","type":"user2"}}}
{"messages":{"id":"id3","owner":{"id":"2907509","type":"user5"},"otherUser":{"id":"2484439","type":"user9"}}}
{"messages":{"id":"id4","owner":{"id":"347793","type":"user1"},"otherUser":{"id":"2907509","type":"user5"}}}
{"messages":{"id":"id5","owner":{"id":"5850517","type":"user4"},"otherUser":{"id":"5850517","type":"user4"}}}
{"messages":{"id":"id6","owner":{"id":"5586286","type":"user8"},"otherUser":{"id":"347793","type":"user10"}}}
I have no idea to do this, I try some code but it not works.
jq -c '.messages[] as $message| $message.owner.type|=.users[]|select(.id==$message.owner.id).name'
Upvotes: 1
Views: 212
Reputation: 116670
If the number of "messages" is very large, then it might be better to process each one separately, to avoid having to read them all into memory.
At any rate, the following illustrates how one can use jq to read in one file to construct a dictionary, and to process a second file on a line-by-line basis.
Let's suppose we have partitioned the JSON into two files (users.json and messages.json), and that the following lines are in process.jq:
# Apply f to composite entities recursively, and to atoms
def walk(f):
. as $in
| if type == "object" then
reduce keys[] as $key
( {}; . + { ($key): ($in[$key] | walk(f)) } ) | f
elif type == "array" then map( walk(f) ) | f
else f
end;
($users | map(.users) | add) as $dict
| walk(if type == "object" and .type == "user"
then .type = $dict[.id]
else .
end)
(If your jq already has walk/1, then its definition can be omitted.)
Then the following command can be used to process the messages:
$ jq --slurpfile users users.json -f process.jq messages.json
Upvotes: 1
Reputation: 134811
Your data has no structure, it'll be easier if you gave it some.
{ users: map(.users // empty), messages: map(.messages // empty) }
When you slurp that file up with this, it'll give you this:
{
"users": [
{ "347793": "user1" },
{ "6560536": "user2" },
{ "6637901": "user3" },
{ "5850517": "user4" },
{ "2907509": "user5" },
{ "6611743": "user6" },
{ "6535592": "user7" },
{ "5586286": "user8" },
{ "2484439": "user9" }
],
"messages": [
{
"id": "id1",
"owner": { "id": "347793", "type": "user" },
"otherUser": { "id": "6560536", "type": "user" }
},
{
"id": "id2",
"owner": { "id": "6637901", "type": "user" },
"otherUser": { "id": "6560536", "type": "user" }
},
{
"id": "id3",
"owner": { "id": "2907509", "type": "user" },
"otherUser": { "id": "2484439", "type": "user" }
},
{
"id": "id4",
"owner": { "id": "347793", "type": "user" },
"otherUser": { "id": "2907509", "type": "user" }
},
{
"id": "id5",
"owner": { "id": "5850517", "type": "user" },
"otherUser": { "id": "5850517", "type": "user" }
},
{
"id": "id6",
"owner": { "id": "5586286", "type": "user" },
"otherUser": { "id": "347793", "type": "user" }
}
]
}
Then doing the replacement should be easier.
(.users | add) as $users
| (.messages[].owner |= (.type = $users[.id]))
| (.messages[].otherUser |= (.type = $users[.id]))
Then if for whatever reason you want to go back to your other structure, then it should be easy (but I wouldn't recommend it).
{ users: .users[] }, { messages: .messages[] }
Upvotes: 0