1

I'm using "ODK" integeration in one of my django project.

I'm getting a json format from a response(request.body) in a django view which is in the way that all the keys in it are non-string. ex :

{
   key1 : "value1",
   key2 : "value2"
}

Since the keys in it are non string I have no idea how to access the values inside the json.I need to know what type of json this one is and how to progress it in order to convert the json to a dictionary.

This is the json file am getting:

{

token: "testauthtoken",
content: "record",
formId: "maintenance_ct",
formVersion: "",

}
  • 1
    How do you they aren't strings? What happens if you iterate over the keys and `print` the type of each one? – DeepSpace Aug 10 '16 at 06:43
  • Thing is when I get the json format's type its shows as a string.so the entire json file is a single string. –  Aug 10 '16 at 06:46
  • JSON only allows key names to be strings; https://stackoverflow.com/questions/8758715/using-number-as-index-json (Try loading that snippet with `json.loads()` and you'll get an exception) – Levi Aug 10 '16 at 06:46
  • 1
    Also, if the key isn't quoted it's not valid json: https://stackoverflow.com/questions/949449/json-spec-does-the-key-have-to-be-surrounded-with-quotes -- it looks like you are trying to parse what is valid javascript but not valid json – Levi Aug 10 '16 at 06:49
  • I can't do json.loads but I've tried json.dumps which works but still I can't access the keys in it. –  Aug 10 '16 at 06:50
  • @Levi so if thats the case then how can I progress further. –  Aug 10 '16 at 06:56
  • Is unclear from your question whether it is coming from your server (in which case whatever library/code is generating the json needs to be corrected to generate valid json) or from a 3rd party site (they need to correct the code, or you need to use nodejs to eval it -- but this opens up a potential security hole as Michael Geary mentioned below) – Levi Aug 10 '16 at 12:04
  • If the json object structure is always exactly 1 level deep and contains only scalar values you could possibly use a regular expression string manipulation to parse it (make sure you handle escape characters correctly) – Levi Aug 10 '16 at 12:06

1 Answers1

2

As others have pointed out, this is not valid JSON, for two reasons: the unquoted key names and the trailing comma at the end.

Your best bet if possible would be to fix the server code that generates this to produce correct JSON instead. Perhaps that code is creating the "JSON" by manually pasting strings together? If so, you could change it to use json.dumps() instead. That will give you valid JSON.

Failing that, you could preprocess the "JSON" text to surround the key names with quotes and to remove the trailing comma. This can be a bit fragile, but if you know the format of the input data will remain similar, it's one way to do it:

import json, re

badJson = '''
{

token: "testauthtoken",
content: "record",
formId: "maintenance_ct",
formVersion: "",

}
'''

print( 'badJson:' )
print( badJson )

goodJson = re.sub( r'\n\s*(\S+)\s*:', r'\n"\1":', badJson )
goodJson = re.sub( r',\s*}', r'\n}', goodJson )
print( 'goodJson:' )
print( goodJson )

goodData = json.loads( goodJson )
print( 'goodData:' )
print( goodData )

This prints:

badJson:

{

token: "testauthtoken",
content: "record",
formId: "maintenance_ct",
formVersion: "",

}

goodJson:

{
"token": "testauthtoken",
"content": "record",
"formId": "maintenance_ct",
"formVersion": ""
}

goodData:
{'formId': 'maintenance_ct', 'content': 'record', 'token': 'testauthtoken', 'formVersion': ''}

When I first wrote this answer I misunderstood the question and provided a JavaScript solution instead of Python. In case this is useful for anyone I'll leave it here:

While the input text is not valid JSON, it is a valid JavaScript object literal. So you can treat it as such and use eval() to parse it. In fact, this is how libraries such as jQuery parsed JSON in old browsers that didn't support JSON.parse().

BEWARE: You had best be sure that you trust the source of this data string, since you are treating it as executable code!

// Set up a string like your input data string.
// All on one line here so we can use a string constant for testing,
// but your multiline data string will work the same.
var dataString = '{ token: "testauthtoken", content: "record", formId: "maintenance_ct", formVersion: "", }'

// Now use eval() to convert it to a JavaScript object.
// We wrap the string in parentheses so it will parse as an expression.
var data = eval( '(' + dataString + ')' );

// Finally, we can access the values.
console.log( 'token: ', data.token );
console.log( 'content: ', data.content );
console.log( 'formId: ', data.formId );
console.log( 'formVersion: ', data.formVersion );
Michael Geary
  • 28,450
  • 9
  • 65
  • 75