Last updated: Apr 8, 2024
Reading timeยท5 min
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': 'Bobby'}" # ๐๏ธ single-quoted # โ๏ธ 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 a single-quoted key and value, which means that it isn't a valid JSON string.
Rather, it's just a Python dictionary that's wrapped in a string.
import json # โ Valid JSON string valid_json = r'{"name": "Bobby Hadz", "age": 30}' # ๐๏ธ no trailing comma a_dict = json.loads(valid_json) print(a_dict) # {'name': 'Bobby Hadz', 'age': 30}
The example string above is valid JSON because the properties and values are double-quoted and there is no trailing comma.
ast.literal_eval
method to evaluate the stringYou 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': 'Bobby Hadz'}" result = ast.literal_eval(invalid_json) print(type(result)) # ๐๏ธ <class 'dict'> print(result) # ๐๏ธ {'name': 'Bobby Hadz'} print(result['name']) # ๐๏ธ Bobby Hadz
The ast.literal_eval() method allows us to safely evaluate a string that contains a Python literal.
If you are trying to convert a Python dictionary to a JSON string, use the
json.dumps()
method.
import json my_dict = { 'id': 1, 'name': 'Bobby Hadz', 'age': 30, } json_str = json.dumps(my_dict) print(json_str) # {"id": 1, "name": "Bobby Hadz", "age": 30} print(type(json_str)) # <class 'str'>
Notice that we didn't wrap the my_dict
variable in single or double quotes to
declare a dictionary.
If you wrap the variable in quotes, you end up declaring a string.
The json.dumps() method converts a Python object to a JSON formatted string.
str.replace
method to replace single with double quotesAn 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'>
The str.replace() method returns a copy of the string with all occurrences of a substring replaced by the provided replacement.
The method takes the following parameters:
Name | Description |
---|---|
old | The substring we want to replace in the string |
new | The replacement for each occurrence of old |
count | Only the first count occurrences are replaced (optional) |
a_str = "'one', 'two', 'three'" result = a_str.replace("'", '"') print(result) # "one", "two", "three"
It's her
.ast.literal_eval
to deal with trailing commasYou can also use the ast.literal_eval
method if your string contains a
trailing comma.
import ast invalid_json = r'{"name": "Bobby Hadz",}' # ๐๏ธ has trailing comma result = ast.literal_eval(invalid_json) print(type(result)) # ๐๏ธ <class 'dict'> print(result) # ๐๏ธ {'name': 'Bobby Hadz'} print(result['name']) # ๐๏ธ Bobby Hadz
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.
pip install pyyaml pip3 install pyyaml
Now you can import and use the module to parse the JSON string.
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.
str.replace()
method to remove trailing commasYou can also use the str.replace()
method to remove the trailing commas from a
string.
import json invalid_json = r'{"name": "Bobby Hadz",}' # ๐๏ธ has trailing comma valid_json = invalid_json.replace( ',}', '}').replace(',]', ']').replace(',)', ')') print(valid_json) # {"name": "Bobby Hadz"} a_dict = json.loads(valid_json) print(a_dict) # {'name': 'Bobby Hadz'}
We chained 3 calls to the str.replace()
method.
The first call removes trailing commas right before a curly brace.
The second call removes trailing commas right before a square bracket.
And the third call removes trailing commas right before a parenthesis.
Here are some examples of valid and invalid JSON strings.
# โ๏ธ invalid JSON (has single-quoted keys and values) invalid_json = r"{'name': 'Alice', 'age': 30, 'tasks' ['a', 'b', 'c']}" # โ valid JSON (double-quoted keys and values) valid_json = r'{"name": "Alice", "age": 30, "tasks": ["a", "b", "c"]}'
Make sure you don't have a trailing comma after the last element.
# โ๏ธ invalid JSON (has a trailing comma after the last key-value pair) invalid_json = r'{"name": "Alice", "age": 30,}' # โ valid JSON (has no trailing comma after the last key-value pair) valid_json = r'{"name": "Alice", "age": 30}'
If you need to parse a JSON string into a native Python object, you have to use
the 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 |
You can hover over the squiggly red line to get additional information on why the error was thrown.
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.
You can learn more about the related topics by checking out the following tutorials: