0

I am currently trying to create a dictionary from a json formatted server response:

{"id": null,{"version": "1.1","result": "9QtirjtH9b","error": null}}

Therefore I am using json.loads(). But I always get the following error:

ValueError: Expecting property name: line 1 column 12 (char 12)

I know that this means that there is an error in the json syntax and I found some threads (like this one) here at stackoverflow, but they did not include an answer that solved my problem.

However, I was not sure if the null value within the json response causes the error, so I had a closer look at the json.org Reference Manual and it seems to be a valid syntax. Any ideas?

Community
  • 1
  • 1
Phidelux
  • 2,043
  • 1
  • 32
  • 50

2 Answers2

2

It's not valid. The outer object needs a property name for the second element; raw values are not valid in an object.

{"id": null, "somename":{"version": "1.1","result": "9QtirjtH9b","error": null}}
Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • Ok, I missed that. But how could I add an own object name to such results without knowing the exact structure of the result? I could not force the server to create a valid response, so I have to fix it myself, but I do not know the exact formatting rules of the server. – Phidelux Jul 03 '13 at 08:57
  • You're going to have to brute-force parse the string. – Ignacio Vazquez-Abrams Jul 03 '13 at 08:58
  • Since the error raises while json parser parses the string, you can not handle it directly. Best approach would be writing your own parser, or you may write a function that will take the string and examine it, and make accurate changes before parsing it with `json`. – Mp0int Jul 03 '13 at 09:02
0

The problem here is the lack of a key for the nested object, not the null. You'd need to find a way to fix that syntax or parse it yourself.

If we make a few assumptions about the syntax, you should be able to use a regular expression to fix the JSON data before decoding:

import re
from itertools import count

def _gen_id(match, count=count()):
    return '{1}"generated_id_{0}":{2}'.format(next(count), *match.groups())

_no_key = re.compile(r'(,)({)')

def fix_json(json_data):
    return _no_key.sub(_gen_id, json_data)

This assumes that any ,{ combo indicates the location of a missing key, and generates one to insert there. That is a reasonable assumption to make, but may break things if you have string data with exactly that sequence.

Demo:

>>> json_data = '{"id": null,{"version": "1.1","result": "9QtirjtH9b","error": null}}'
>>> fix_json(json_data)
'{"id": null,"generated_id_0":{"version": "1.1","result": "9QtirjtH9b","error": null}}'
>>> json.loads(fix_json(json_data))
{u'id': None, u'generated_id_1': {u'version': u'1.1', u'result': u'9QtirjtH9b', u'error': None}}
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343