Reputation: 377
In my app using Python 2.6.9 I have this incoming JSON as a unicode string:
{"devices": "{1540702298: u\"{'on': u'True', 'group': '2', 'time': u'2015-06-04 16:37:52', 'value': u'74.1', 'lastChange': u'2015-06-05 09:28:10'}\"}"}
I have tried in various ways to parse it but I still get the same error...
For example:
a = unicode({"devices": "{1540702298: u\"{'on': u'True', 'group': '2', 'energyAccumBaseTime': u'2015-06-04 16:37:52', 'sensorValueRaw': u'74.1', 'lastChange': u'2015-06-05 09:28:10', 'energyAccumTotal': u'1.3', 'sensorValueUi': u'74.1'}\"}"})
b = json.loads(a)
print b['devices'] # all good I get the contents...
but when I do...
for k, v in b['devices'].iteritems():
print k
I get the error:
'unicode' object has no attribute 'iteritems'
How can I parse this incoming JSON in full?
Upvotes: 0
Views: 19872
Reputation: 1123420
The outer object may be JSON, but it contains a string that itself is a Python dictionary literal, containing Unicode literals as values.
Someone did this:
python_dictionary = {}
python_dictionary[integer_key] = str(another_dictionary)
outer_object {"devices": str(python_dictionary)}
before encoding the outer_object
to JSON. Each value in that dictionary is itself another string representing a Python dictionary, and those dictionaries contain more strings representing dictionaries, like so many Matryoshka dolls.
You can use the ast.literal_eval()
function to turn that back into Python objects:
import ast
import json
yourobject = json.loads(jsondata)
dictionary = ast.literal_eval(yourobject['devices'])
for key, nested in dictionary.iteritems():
nested = ast.literal_eval(nested)
print key, nested
but you should really fix whatever produced the string to avoid storing the nested dictionary as a string. Note that the keys in that nested dictionary are integers; those would have to be converted to strings to work in JSON.
Demo:
>>> import json
>>> import ast
>>> jsondata = r'''{"devices": "{1540702298: u\"{'on': u'True', 'group': '2', 'time': u'2015-06-04 16:37:52', 'value': u'74.1', 'lastChange': u'2015-06-05 09:28:10'}\"}"}'''
>>> yourobject = json.loads(jsondata)
>>> type(yourobject['devices'])
<type 'unicode'>
>>> ast.literal_eval(yourobject['devices'])
{1540702298: u"{'on': u'True', 'group': '2', 'time': u'2015-06-04 16:37:52', 'value': u'74.1', 'lastChange': u'2015-06-05 09:28:10'}"}
>>> dictionary = ast.literal_eval(yourobject['devices'])
>>> dictionary[1540702298]
u"{'on': u'True', 'group': '2', 'time': u'2015-06-04 16:37:52', 'value': u'74.1', 'lastChange': u'2015-06-05 09:28:10'}"
>>> type(dictionary[1540702298])
<type 'unicode'>
>>> for key, nested in dictionary.iteritems():
... nested = ast.literal_eval(nested)
... print key, nested
...
1540702298 {'on': u'True', 'lastChange': u'2015-06-05 09:28:10', 'group': '2', 'value': u'74.1', 'time': u'2015-06-04 16:37:52'}
Upvotes: 10