Python: Add JSON into Existing JSON
Question:
Suppose I have two json files. I would like to be able to load both, then add the entries from the second into the first. This may include adding fields or list entries. Something like the following example:
file1.json:
{ "fruit": [ { "name": "apple", "color": "red" }, { "name": "orange", "color": "orange" } ] }
file2.json:
{ "fruit": [ { "name": "strawberry", "color": "red", "size": "small" }, { "name": "orange", "size": "medium" } ] }
result:
{ "fruit": [ { "name": "apple", "color": "red" }, { "name": "orange", "color": "orange", "size": "medium" }, { "name": "strawberry", "color": "red", "size": "small" } ] }
At first I thought to load them into dictionaries and try something like update:
import simplejson
filea = open("file1.json", 'r')
dicta = simplejson.loads(filea.read())
fileb = open("file2.json", 'r')
dictb = simplejson.loads(fileb.read())
filea.close()
fileb.close()
dicta.update(dictb)
Since both dictionaries have an entry for "fruit" I was hoping that they would merge, but it simple overrides the entry in dicta with the entry in dictb.
I realize I could write code to loop through this example, but the actual files I’m using are far larger and more complicated. I was wondering if there was a library out there that did something like this already before I go reinventing the wheel. For what it’s worth, I am using Python 2.6.2.
Thanks for any advice or suggestions!
Answers:
You’ll need to extend the lists checking each value. There’s no way Python can now you want to merge them based on name
item of dictionaries:
def merge(lsta, lstb):
for i in lstb:
for j in lsta:
if j['name'] == i['name']:
j.update(i)
break
else:
lsta.append(i)
for k,v in dictb.items():
merge(dicta.setdefault(k, []), v)
So the dicta
variable will be:
{'fruit': [{'color': 'red', 'name': 'apple'},
{'color': 'orange', 'name': 'orange', 'size': 'medium'},
{'color': 'red', 'name': 'strawberry', 'size': 'small'}]}
Given parsed json in a list parsed_json
:
transformed_data = []
for data in parsed_json:
transformed_data.append({})
for fruit in data['fruit']:
fruit_copy = fruit.copy()
transformed_data[-1][fruit_copy.pop('name')] = fruit_copy
merged_fruit = defaultdict(dict)
for name, values in transformed_data.iteritems():
merged_fruit[name].update(values)
You could do it with a dict comprehension in 2.7+, but you said 2.6.2. Given your statement that in the real world, you are merging on more than one field, you can just change the key when setting transformed_data
members to be whatever fields from the source you want. If you don’t care about destroying the original parsed data, you can also drop the copy
.
Suppose I have two json files. I would like to be able to load both, then add the entries from the second into the first. This may include adding fields or list entries. Something like the following example:
file1.json:
{ "fruit": [ { "name": "apple", "color": "red" }, { "name": "orange", "color": "orange" } ] }
file2.json:
{ "fruit": [ { "name": "strawberry", "color": "red", "size": "small" }, { "name": "orange", "size": "medium" } ] }
result:
{ "fruit": [ { "name": "apple", "color": "red" }, { "name": "orange", "color": "orange", "size": "medium" }, { "name": "strawberry", "color": "red", "size": "small" } ] }
At first I thought to load them into dictionaries and try something like update:
import simplejson
filea = open("file1.json", 'r')
dicta = simplejson.loads(filea.read())
fileb = open("file2.json", 'r')
dictb = simplejson.loads(fileb.read())
filea.close()
fileb.close()
dicta.update(dictb)
Since both dictionaries have an entry for "fruit" I was hoping that they would merge, but it simple overrides the entry in dicta with the entry in dictb.
I realize I could write code to loop through this example, but the actual files I’m using are far larger and more complicated. I was wondering if there was a library out there that did something like this already before I go reinventing the wheel. For what it’s worth, I am using Python 2.6.2.
Thanks for any advice or suggestions!
You’ll need to extend the lists checking each value. There’s no way Python can now you want to merge them based on name
item of dictionaries:
def merge(lsta, lstb):
for i in lstb:
for j in lsta:
if j['name'] == i['name']:
j.update(i)
break
else:
lsta.append(i)
for k,v in dictb.items():
merge(dicta.setdefault(k, []), v)
So the dicta
variable will be:
{'fruit': [{'color': 'red', 'name': 'apple'},
{'color': 'orange', 'name': 'orange', 'size': 'medium'},
{'color': 'red', 'name': 'strawberry', 'size': 'small'}]}
Given parsed json in a list parsed_json
:
transformed_data = []
for data in parsed_json:
transformed_data.append({})
for fruit in data['fruit']:
fruit_copy = fruit.copy()
transformed_data[-1][fruit_copy.pop('name')] = fruit_copy
merged_fruit = defaultdict(dict)
for name, values in transformed_data.iteritems():
merged_fruit[name].update(values)
You could do it with a dict comprehension in 2.7+, but you said 2.6.2. Given your statement that in the real world, you are merging on more than one field, you can just change the key when setting transformed_data
members to be whatever fields from the source you want. If you don’t care about destroying the original parsed data, you can also drop the copy
.