Kostas
Kostas

Reputation: 377

Python: 'unicode' object has no attribute 'iteritems'

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

Answers (1)

Martijn Pieters
Martijn Pieters

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

Related Questions