Reputation: 655
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
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
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
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