Borislav Hadzhiev
Sun Apr 24 2022·3 min read
Photo by Johannes Plenio
The Python "JSONDecodeError: Expecting property name enclosed in double
quotes: line 1 column 2 (char 1)" occurs when we try to parse an invalid JSON
string (e.g. single-quoted keys or values, or a trailing comma). Use the
ast.literal_eval()
method to solve the error.
Here is an example of how the error occurs.
import json invalid_json = r"{'name': 'Alice'}" # ⛔️ json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1) result = json.loads(invalid_json)
Notice that the string has single-quoted key and value, which means that it isn't a valid JSON string.
Rather, it's just Python dictionary that's wrapped in a string.
You can solve the error by using the ast.literal_eval
method to evaluate the
string that contains a Python literal.
import ast invalid_json = r"{'name': 'Alice'}" result = ast.literal_eval(invalid_json) print(type(result)) # 👉️ <class 'dict'> print(result) # 👉️ {'name': 'Alice'} print(result['name']) # 👉️ Alice
The ast.literal_eval method allows us to safely evaluate a string that contains a Python literal.
An alternative approach is to use the str.replace()
method to replace all
single quotes in the string with double quotes.
import json invalid_json = r"{'name': 'Alice'}" valid_json = invalid_json.replace("\'", "\"") print(valid_json) # 👉️ '{"name": "Alice"}' my_dict = json.loads(valid_json) print(my_dict) # 👉️ {'name': 'Alice'} print(type(my_dict)) # 👉️ <class 'dict'>
It's her
.You can also use the ast.literal_eval
method if your string contains a
trailing comma.
import ast invalid_json = r'{"name": "Alice",}' result = ast.literal_eval(invalid_json) print(type(result)) # 👉️ <class 'dict'> print(result) # 👉️ {'name': 'Alice'} print(result['name']) # 👉️ Alice
The trailing comma also makes the string invalid JSON, but Python dictionaries are allowed to have a trailing comma after the last key-value pair.
Alternatively, you can try using the yaml.safe_load()
method.
Make sure you have pyyaml
installed by running pip install pyyaml
.
import yaml invalid_json = r'{"name": "Alice",}' # 👈️ has trailing comma my_dict = yaml.safe_load(invalid_json) print(my_dict) # 👉️ {'name': 'Alice'} print(type(my_dict)) # 👉️ <class 'dict'>
Make sure the value you are trying to parse is a JSON string and has not been already parsed into a native Python object.
json.loads()
method, and if you need to convert a Python object into a JSON string, you have to use the json.dumps()
method.import json json_str = r'{"name": "Alice", "age": 30}' # ✅ parse JSON string to Python native dict my_dict = json.loads(json_str) print(type(my_dict)) # 👉️ <class 'dict'> # ✅ convert Python native dict to a JSON string my_json_str = json.dumps(my_dict) print(type(my_json_str)) # 👉️ <class 'str'>
The json.loads()
method basically helps us load a Python native object (e.g. a
dictionary or a list) from a JSON string.
The json.dumps method converts a Python object to a JSON formatted string.
The JSONEncoder
class supports the following objects and types by default.
Python | JSON |
---|---|
dict | object |
list, tuple | array |
str | string |
int, float, int and float derived Enums | number |
True | true |
False | false |
None | null |
If you aren't sure what type of object a variable stores, use the built-in
type()
class.
my_dict = {'name': 'Alice', 'age': 30} print(type(my_dict)) # 👉️ <class 'dict'> print(isinstance(my_dict, dict)) # 👉️ True my_str = 'hello world' print(type(my_str)) # 👉️ <class 'str'> print(isinstance(my_str, str)) # 👉️ True
The type class returns the type of an object.
The isinstance
function returns True
if the passed in object is an instance or a subclass of
the passed in class.