How to select multiple JSON Objects using python

Question:

I have a Json data as following. The Json has many such objects with same NameId’s:

[{
    "NameId": "name1",
    "exp": {
        "exp1": "test1"
    }
}, {
    "NameId": "name1",
    "exp": {
        "exp2": "test2"
    }
}

]

Now, what I am after is to create a new Json Object that has a merged exp and create a file something like below, so that I do not have multiple NameId:

[{
"NameId": "name1",
"exp": {
"exp1": "test1",
"exp2": "test2"
}
}
]

Is there a possibility I can achive it using Python?

Asked By: Geebee

||

Answers:

You can use itertools.groupby and functools.reduce

d = [{
    "NameId": "name1",
    "exp": {
        "exp1": "test1"
    }
}, {
    "NameId": "name1",
    "exp": {
        "exp2": "test2"
    }
}]
from itertools import groupby
[ {'NameId': k, 'exp': reduce(lambda x,y : {**x["exp"], **y["exp"]} , v) } for k,v in groupby(sorted(d, key=lambda x: x["NameId"]), lambda x: x["NameId"]) ]

#output
[{'NameId': 'name1', 'exp': {'exp1': 'test1', 'exp2': 'test2'}}]
Answered By: Deepak Tripathi

You can do the manual work, merging the entries while rebuilding the structure. You can keep a dictionary with the exp to merge them.

import json

jsonData = [{
    "NameId": "name1",
    "exp": {
        "exp1": "test1"
    }
}, {
    "NameId": "name1",
    "exp": {
        "exp2": "test2"
    }
}, {
    "NameId": "name2",
    "exp": {
        "exp3": "test3"
    }
}]

result = []
expsDict = {}
for entry in jsonData:
    nameId = entry["NameId"]
    exp = entry["exp"]
    if nameId in expsDict:
        # Merge exp into resultExp.
        # Note that resultExp belongs to both result and expsDict,
        # changes made will be reflected in both containers!
        resultExp = expsDict[nameId]
        for (expName, expValue) in exp.items():
            resultExp[expName] = expValue
    else:
        # Copy copy copy, otherwise merging would modify jsonData too!
        exp = exp.copy()
        entry = entry.copy()
        entry["exp"] = exp
        # Add a new item to the result
        result.append(entry)
        # Store exp to later merge other entries with the same name.
        expsDict[nameId] = exp

print(result)
Answered By: Wyrzutek
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.