Quick answer
Python’s JSON parser expected an object key wrapped in double quotes but found something else — single quotes, an unquoted key, or a trailing comma. JSON only allows double quotes for keys and strings. The usual cause is feeding json.loads() a Python dict converted with str() instead of json.dumps().
The exact error string
The traceback ends with a line that names the position of the offending character:
Traceback (most recent call last):
File "app.py", line 5, in <module>
data = json.loads(text)
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
Unlike Expecting value: line 1 column 1 (char 0) — where the whole string is not JSON — this error means parsing started fine (it saw an opening {) but then hit a key that is not a double-quoted string.
Where this error usually comes from
The five most common situations that produce this error:
- Calling
json.loads(str(my_dict))— Python’sstr()serializes a dict with single quotes;json.loads()rejects them immediately. - Reading a hand-edited
config.json— trailing commas or single quotes creep in when JSON is edited without a linter. - Copying a JavaScript object literal — JS allows bare (unquoted) keys and single-quoted strings; JSON does not.
- Consuming a broken API response — the server returns a Python
repr()output or debug string instead of valid JSON. - Template-generated JSON — a string-formatting template produces single-quoted values or accidentally drops a closing quote.
Cause 1: Single quotes instead of double quotes
This is by far the most common cause. A Python dict converted to a string with str() uses single quotes, which are valid Python but invalid JSON:
import json
text = "{'name': 'Alice', 'age': 30}" # single quotes — looks like a Python dict
data = json.loads(text)
# JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
The parser reads the {, then expects a " to start the first key — but finds a ' at column 2. JSON requires double quotes everywhere.
Cause 2: A trailing comma
A comma after the last item makes the parser expect another key, but it finds the closing brace:
import json
text = '{"name": "Alice", "age": 30,}' # trailing comma after 30
data = json.loads(text)
# JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 29 (char 28)
Here the position points at the } — the parser wanted a new key there. Remove the comma after the final value. (See the JavaScript version of this issue in JSON Trailing Comma.)
Cause 3: Unquoted keys (JavaScript-style)
JavaScript object literals allow bare keys; JSON does not. Copying an object straight out of JS source produces invalid JSON:
import json
text = '{name: "Alice", age: 30}' # unquoted keys
data = json.loads(text)
# JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
Every key must be wrapped in double quotes: {"name": "Alice", "age": 30}.
Diagnose in three steps
Before reaching for a fix, run print(repr(text)) on the string you are passing to json.loads(). The repr() output makes quote style and invisible characters visible at a glance:
print(repr(text))
# "{'name': 'Alice', 'age': 30}" ← outer double, inner single → Cause 1
# '{"name": "Alice", "age": 30,}' ← ends with ,} → Cause 2
# '{name: "Alice", age: 30}' ← bare word before colon → Cause 3
Match what you see to the fix:
| What repr() shows | Root cause | Fix |
|---|---|---|
starts with {' |
Single quotes (Python repr) | ast.literal_eval() → json.dumps() |
contains ,} or ,] |
Trailing comma | Remove the comma after the last item |
{word: (no quotes) |
Unquoted JS-style key | Wrap every key in " |
The right fix depends on what you have
If you have a real Python dict
Do not build JSON by hand or with str(). Use json.dumps(), which always emits valid double-quoted JSON:
import json
obj = {"name": "Alice", "age": 30}
text = json.dumps(obj) # '{"name": "Alice", "age": 30}' ✓ valid JSON
data = json.loads(text) # round-trips cleanly
If you have a string that looks like a Python dict
When the single-quoted text comes from a log, a database column, or str(dict) output, convert it back to a real dict with ast.literal_eval() (safe), then re-serialize with json.dumps():
import ast
import json
text = "{'name': 'Alice', 'age': 30}" # single-quoted Python dict literal
obj = ast.literal_eval(text) # safely → {'name': 'Alice', 'age': 30}
clean_json = json.dumps(obj) # '{"name": "Alice", "age": 30}' ✓
data = json.loads(clean_json)
Never use eval() on untrusted input — ast.literal_eval() only evaluates literals and is safe for this purpose.
If the JSON is hand-written
Fix it at the source: replace single quotes with double quotes, quote every key, and remove trailing commas. Paste it into a validator to catch every issue at once.
Fix invalid JSON in seconds
Paste the bad JSON into the validator — it reports the exact line, column, and character that caused the failure:
# Input
{'name': 'Alice'}
# Validator output
Line 1, column 2: Expecting property name enclosed in double quotes
# Input
{"name": "Alice", "age": 30,}
# Validator output
Line 1, column 29: Expecting property name enclosed in double quotes
Frequently Asked Questions
What does Expecting property name enclosed in double quotes mean?
It means Python's json parser expected the next thing inside an object to be a key wrapped in double quotes, but found something else — a single quote, an unquoted word, or a closing brace after a trailing comma. JSON requires every object key to be a double-quoted string. The most common cause is feeding json.loads() a Python dict converted to text with str() instead of json.dumps().
Why does single-quoted JSON fail in Python?
The JSON specification only allows double quotes for strings and keys. A string like {'name': 'Alice'} is valid Python but invalid JSON, so json.loads() rejects it at the first single quote. Convert Python objects to JSON with json.dumps(), which always emits double quotes.
How do I convert a Python dict string to JSON?
If you have a real Python dict, use json.dumps(my_dict). If you only have a string that looks like a Python dict (with single quotes), use ast.literal_eval() to safely turn it back into a dict, then json.dumps() to serialize it correctly. Never use eval() on untrusted input.
Does a trailing comma cause this error?
Yes. A trailing comma after the last item in an object — like {"a": 1,} — makes the parser expect another key after the comma, but it finds the closing brace instead. JSON does not allow trailing commas. Remove the comma after the final item.
Are unquoted keys allowed in JSON?
No. JavaScript object literals allow unquoted keys like {name: "Alice"}, but JSON does not. Every key must be a double-quoted string: {"name": "Alice"}. If you are copying an object from JavaScript source, you must quote every key before it is valid JSON.