I'm using jq to try and merge 2 json files into one unique file.
The result is close to what I was looking for, but not just right.
File 1:
{ "series": "Harry Potter Movie Series", "writer": "J.K. Rowling", "movies": [ { "title": "Harry Potter and the Philosopher's Stone", "actors": [ { "names": [ "Emma Watson", "Other actor" ], "other": "Some value" } ] }, { "title": "Harry Potter and the Chamber of Secrets", "actors": [ { "names": [ "Emma Watson" ], "other": "Some value" } ] } ] } File 2:
{ "series": "Harry Potter Movie Series", "producer": "David Heyman", "movies": [ { "title": "Harry Potter and the Philosopher's Stone", "year": "2001" }, { "title": "Harry Potter and the Chamber of Secrets", "year": "2002" } ] } Expected result:
{ "series": "Harry Potter Movie Series", "writer": "J.K. Rowling", "movies": [ { "title": "Harry Potter and the Philosopher's Stone", "year": "2001", "actors": [ { "names": [ "Emma Watson", "Other actor" ], "other": "Some value" } ] }, { "title": "Harry Potter and the Chamber of Secrets", "year": "2001", "actors": [ { "names": [ "Emma Watson" ], "other": "Some value" } ] } ], "producer": "David Heyman" } Best result I've got so far (only arrays with actors are missing):
{ "series": "Harry Potter Movie Series", "writer": "J.K. Rowling", "movies": [ { "title": "Harry Potter and the Philosopher's Stone", "year": "2001" }, { "title": "Harry Potter and the Chamber of Secrets", "year": "2002" } ], "producer": "David Heyman" } Using one of the commands below:
jq -s '.[0] * .[1]' file1 file2
jq --slurp 'add' file1 file2
jq '. * input' file1 file2
If I switch order of files I either end up losing 'actors' from file1 or 'year' from file2.
How it should work:
- the elements in file 2 will be leading and should replace the matching elements in file 1.
- the elements in file 1 that doesn't exist in file 2 (like writer and movies[].actors elements) shouldn't be deleted
- the elements in file 2 that doesn't exist yet in file 1 will be added (like producer and movies[].year).
- a title is unique and should by default not occur more then once, but if it does remove the duplicates.
I would assume there is a solution to get these movies arrays perfectly merged with jq.
*(not+) for a deep merge, while the middle one usesaddwhich iterates through the array using+, thus it is just a top-level merge. Iteration through the slurped files using*would bejq --slurp 'reduce .[] as $i ({}; . * $i)' file1 file2(only useful for more than two or a variable number of files, otherwise.[0] * .[1]is just as good).