Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

String format a JSON string gives KeyError

Why does this code give a KeyError?

output_format = """ {      "File": "{filename}",      "Success": {success},      "ErrorMessage": "{error_msg}",      "LogIdentifier": "{log_identifier}"  } """  print output_format.format(filename='My_file_name',                            success=True,                            error_msg='',                            log_identifier='123') 

Error message:

KeyError: ' "File"' 
like image 746
Shane Avatar asked May 03 '13 10:05

Shane


People also ask

How to handle KeyError in JSON?

To solve the (JSON) KeyError exception in Python, use the json. loads() method to parse the JSON string into a native Python object and conditionally check if the key is present in the dictionary before accessing it.

How do you convert a string to a JSON object in Python?

Use the json.loads() function. The json. loads() function accepts as input a valid string and converts it to a Python dictionary. This process is called deserialization – the act of converting a string to an object.

What is JSON loads in Python?

loads() method can be used to parse a valid JSON string and convert it into a Python Dictionary. It is mainly used for deserializing native string, byte, or byte array which consists of JSON data into Python Dictionary.


2 Answers

You need to double the outer braces; otherwise Python thinks { "File".. is a reference too:

output_format = '{{ "File": "{filename}", "Success": {success}, "ErrorMessage": "{error_msg}", "LogIdentifier": "{log_identifier}" }}' 

Result:

>>> print output_format.format(filename='My_file_name', ...                            success=True, ...                            error_msg='', ...                            log_identifier='123') { "File": "My_file_name", "Success": True, "ErrorMessage": "", "LogIdentifier": "123" } 

If, indicentally, you are producing JSON output, you'd be better off using the json module:

>>> import json >>> print json.dumps({'File': 'My_file_name', ...                   'Success': True, ...                   'ErrorMessage': '', ...                   'LogIdentifier': '123'}) {"LogIdentifier": "123", "ErrorMessage": "", "Success": true, "File": "My_file_name"} 

Note the lowercase true in the output, as required by the JSON standard.

like image 64
Martijn Pieters Avatar answered Oct 12 '22 05:10

Martijn Pieters


As mentioned by Tudor in a comment to another answer, the Template class was the solution that worked best for me. I'm dealing with nested dictionaries or list of dictionaries and handling those were not as straightforward.

Using Template though the solution is quite simple.

I start with a dictionary that is converted into a string. I then replace all instances of { with ${ which is the Template identifier to substitute a placeholder.

The key point of getting this to work is using the Template method safe_substitute. It will replace all valid placeholders like ${user_id} but ignore any invalid ones that are part of the dictionary structure, like ${'name': 'John', ....

After the substitution is done I remove any leftovers $ and convert the string back to a dictionary.

In the code bellow, resolve_placeholders returns a dictionary where each key matches a placeholder in the payload string and the value is substituted by the Template class.

from string import Template . . . payload = json.dumps(payload) payload = payload.replace('{', '${') replace_values = self.resolve_placeholders(payload) if replace_values:     string_template = Template(payload)     payload = string_template.safe_substitute(replace_values) payload = payload.replace('${', '{') payload = json.loads(payload) 
like image 26
Marcos Avatar answered Oct 12 '22 06:10

Marcos