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!

Asked By: Matthew Pape

||

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'}]}
Answered By: JBernardo

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.

Answered By: Silas Ray
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.