I've tried using
jq "reduce inputs.skins as $s (.; .skins += $s)" file1.json file2.json > combined.json
but it just creates two boots.name and fun.name from each file
any way I can use jq and combine the objects and arrays without having duplicates?
I apologize for any confusion, jq is kind of complicated to find an easy tutorial for me to understand
file1.json
{
"skins": [
{
"Item Shortname": "boots.name",
"skins": [
2,
25,
41,
]
},
{
"Item Shortname": "fun.name",
"skins": [
12,
8,
]
}
]
}
file2.json
{
"skins": [
{
"Item Shortname": "boots.name",
"skins": [
2,
20,
]
},
{
"Item Shortname": "fun.name",
"skins": [
90,
6,
82,
]
}
]
}
combined.json
{
"skins": [
{
"Item Shortname": "boots.name",
"skins": [
2,
20,
25,
41,
]
},
{
"Item Shortname": "fun.name",
"skins": [
90,
6,
82,
12,
8,
]
}
]
}
The tricky part here is meeting the apparent uniqueness requirements, for which the following generic filter can be used:
# emit a stream of the distinct items in `stream`
def uniques(stream):
foreach stream as $s ({};
($s|type) as $t
| (if $t == "string" then $s else ($s|tostring) end) as $y
| if .[$t][$y] then .emit = false else .emit = true | (.item = $s) | (.[$t][$y] = true) end;
if .emit then .item else empty end );
This ensures the ordering is preserved. It's a bit tricky because it is completely generic -- it allows both 1
and "1"
and distinguishes between them, just as unique
does.
(If the ordering did not matter, then you could use unique
.)
So, assuming an invocation along the lines of
jq -s -f program.jq file1.json file2.json
you would place the above def followed by the following “main” program in program.jq:
.[0] as $file1 | .[1] as $file2
| (INDEX($file1.skins[]; .["Item Shortname"]) | map_values(.skins)) as $dict
| $file2
| .skins |= map( .["Item Shortname"] as $name
| .skins += $dict[$name]
| .skins |= [uniques(.[])] )
A better solution would avoid the -s option (e.g. as shown below), but the above method of feeding the two files to jq is at least straightforward, and will work regardless of which version of jq you are using.
input
One way to avoid slurping the two files would be to use input
in conjunction with the -n command line option instead of -s. The "main" part of the jq program would then be as follows:
(INDEX(input.skins[]; .["Item Shortname"]) | map_values(.skins)) as $dict
| input
| .skins |= map( .["Item Shortname"] as $name
| .skins += $dict[$name]
| .skins |= [uniques(.[])] )