0

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?

2 Answers 2

1

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)
Sign up to request clarification or add additional context in comments.

7 Comments

Thank you so much, you made it look like it was very easy :) and I have wasted 2 days on it already ....
@Geebee Happy to help. Please note my edit, resultExp was not shared only between the result and the dictionary, but also the original data! You can print(jsonData) at the end to see the difference
If I understand the question, the magic is that dictionaries are stored by reference. When you do list.append(x) or dict[key]=x and then modify x (e.g. x[a]=b), also the element of the list and the dict are modified, because they are different references of the same object. Also dict[key][a]=b modifies x. So the modifications done to resultExp are reflected to expsDict[nameId], the exp that was assigned to it in the else part, and the entry["exp"] that has been added to the result, because they are all the same object!
There is a difference between assigning a variable and modifying it. When you assign, you modify only that variable, because you are changing what it references; for instance a={}, b=a, b=3, print(a) will display {}, because at the end b references to 3 and a has nothing to do with it. Instead, when the variable is modified, all references get modified; for instance, a={}, b=a, b[0]=3, print(a) will display {0:3}, because a and b are references of the same dictionary. It is difficult indeed!
Note that the operator x+=y behaves like an assignment, not a modification, because it is only a shortcut for x=x+y. For instance, a=0, b=a, b+=3, print(a) will display 0, just like if there was b=b+3 instead of b+=3. b is assigned to something different and hence loses the reference to a.
|
0

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'}}]

2 Comments

Thanks @Deepak, I did not get a chance to go through your solution. I will go through it and will let you know the outcome.
Sure @Geebee Take your time

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.