Berdus
Berdus

Reputation: 655

In place editing of Python dictionary or parsing json to object

I am by no means a Python Guru, but I know my way around. For the past two hours however I've been banging my head against the following:

I am parsing a JSON response from a WCF Webservice using the json.loads() function. The result is a Python dictionary which I am using throughout my application. However, I now have the need to obfuscate the id, reseller_id etc. for use in HTTP GET requests.

This is an example of a response: (note, I have many of these responses, so I am looking for a generic solution.) I want to replace the value of any id with a hash of the id value

{
    "token":"String content",
    "user":{
        "distributor":{
            "email":"String content",
            "id":2147483647,
            "name":"String content"
        },
        "email":"String content",
        "first_name":"String content",
        "id":2147483647,
        "last_name":"String content",
        "reseller":{
            "email":"String content",
            "id":2147483647,
            "name":"String content",
            "portal_css":"String content",
            "portal_logo":"String content",
            "portal_name":"String content",
            "portal_url":"String content"
        },
        "role":2147483647
    }
}

I have tried all kinds of strategies using code like:

result = json.loads(json_result, object_hook=lambda d: namedtuple('X', d.keys())(*d.values()))

and

def fun(d):
    if 'id' in d:
        yield d['id']
    for k in d:
        if isinstance(d[k], list):
            for i in d[k]:
                for j in fun(i):
                    yield j

I can't get it to work properly. So:

Question 1: Can I convert json to (Anonymous) Python Objects and how?

Question 2: Can I edit the resulting dict in place?

Question 3: When all else fails; Does anybody have an idea how to achieve this?

Thanks a lot!

Upvotes: 2

Views: 2509

Answers (3)

istruble
istruble

Reputation: 13692

Yes. json.loads returns a Python object based on the actual json object. Check the conversion table for more details. There is no need to look for a special anonymous object like you might in .Net land.

result = json.loads(json_text)

You can edit this result in place:

result['user']['id'] = 'some_new_value' 

Try the object_pairs_hook argument when parsing your json:

def hide_ids(o):
    d = dict(o)
    if 'id' in d:
        d['id'] = '----{}----'.format(d['id'])
    return d

result = json.loads(json_text, object_pairs_hook=hide_ids)

Just modify with your preferred obfuscation logic and you should be good to go.

Upvotes: 1

Werner Smit
Werner Smit

Reputation: 2061

This is a solution that I quickly put together. It recurses through your dictionary and replaces the value when the key is id. This isn't the final solution as it doesn't support lists, but I'm sure if this works for you, you can take it from there?

def f(d):
    _dict = {}
    for k, v in d.items():
        if isinstance(v, dict):
            _dict.update({k: f(v)})
        else:
            if k == 'id':
                print 'id found', v
                v = EncryptValueHere(v)
            _dict.update({k:v})

    return _dict

Upvotes: 1

Elmar Peise
Elmar Peise

Reputation: 15413

json.loads(data)

parses the json string data and returns a Python dict, which I guess you could call anonymous, until you assign it to a variable:

d = json.loads(data)

You can then modify the dict in place. Assuming that all of your responses have the same structure, you can hash the id as follows:

d["user"]["id"] = your_hash_function(d["user"]["id"])

Upvotes: 3

Related Questions