Single quotes are not valid JSON: Fixing json.loads() in Python
Python json.loads() rejects single quotes because JSON requires double quotes. Learn the causes, fixes, and a safe parsing pattern.
Have broken JSON right now? Fix it free in under 1 second — no signup.
Fix My JSON →JSON strings and keys must use double quotes, so json.loads() fails on text that uses single quotes. Python reports it as a JSONDecodeError, usually "Expecting property name enclosed in double quotes".
What “Single quotes are not valid JSON” means
The parser found a single quote where JSON allows only a double quote. The JSON standard defines strings and object keys with double quotation marks only. Python's json module follows that rule. It does not guess what you meant, so it stops at the first single quote and reports the line and column.
Causes and the fix for each
A Python dict was printed with str() or repr() and treated as JSON.
Python writes dict keys and string values with single quotes when you call str() on a dict or print it. The result looks like JSON but is a Python literal. Sending that text to json.loads() fails at the first key, usually at column 2.
Before (fails):{'id': 1, 'name': 'Ana'}
After (valid):
{"id": 1, "name": "Ana"}
The key uses double quotes but the value uses single quotes.
The key parses without trouble, but the value starts with a single quote. Python then reports "Expecting value" and points at the column where the value begins. This often happens when someone edits one field by hand or merges two sources that quote strings differently.
Before (fails):{"name": 'Ana'}
After (valid):
{"name": "Ana"}
The text is a JavaScript object literal, not JSON.
JavaScript allows unquoted keys and single-quoted strings in object literals. JSON allows neither. Config snippets copied from front-end code or documentation often look valid but fail in Python, because json.loads() expects every key and string to be wrapped in double quotes.
Before (fails):{name: 'Ana'}
After (valid):
{"name": "Ana"}
An apostrophe inside a single-quoted string was left as is.
A value wrapped in single quotes can contain an apostrophe, which ends the string early in many languages. Once you switch to double quotes, the apostrophe is a normal character and needs no escape. Only a double quote inside the string needs a backslash.
Before (fails):{"note": 'it's fine'}
After (valid):
{"note": "it's fine"}
Python-only values such as True, False and None appear next to the single quotes.
A repr() of a dict often carries more than single quotes. Booleans are written True and False, and null is written None. Fixing quotes alone moves the error to the next token. JSON needs lowercase true and false, and null.
Before (fails):{'active': True, 'owner': None}
After (valid):
{"active": true, "owner": null}
How to fix it in Python
- Read the error position. The line and column in the JSONDecodeError point at the first single quote the parser could not accept.
- If you control the producer, serialize with json.dumps() instead of str(). It writes double quotes, true, false and null correctly.
- If the text came from an API, a file or an LLM, paste it into the Repair tool to convert quotes and literals, then check the result in the Validator.
- If the text is a trusted Python literal, parse it with ast.literal_eval() and write it back out with json.dumps().
- Re-run json.loads() on the fixed text. If a new error appears further along, fix that one next, because the parser reports only the first problem.
import ast
import json
def parse_loose(text):
try:
return json.loads(text)
except json.JSONDecodeError as err:
first_error = err
try:
# Handles Python literals such as {'a': 1, 'b': True}
value = ast.literal_eval(text)
except (ValueError, SyntaxError):
raise first_error
# Round-trip to confirm the value is JSON-safe
return json.loads(json.dumps(value))
print(parse_loose("{'name': 'Ana', 'active': True}"))
Variants of the message
| Message | Cause | Fix |
|---|---|---|
| Expecting property name enclosed in double quotes: line 1 column 2 (char 1) | An object key is wrapped in single quotes, or has no quotes. | Wrap each key in double quotes. |
| Expecting value: line 1 column 10 (char 9) | A value starts with a single quote after a valid key. | Change the value's single quotes to double quotes. |
| Expecting value: line 1 column 1 (char 0) | The whole text is empty, or starts with something that is not JSON, such as a single-quoted string. | Check that the input is not empty and starts with { or [ or a double-quoted string. |
| Expecting ',' delimiter: line 1 column 20 (char 19) | An apostrophe or quote inside a string ended it early, so the next character is unexpected. | Use double quotes around the string and escape any inner double quote. |
Related errors
- [Fix JSON Single Quote Errors Instantly — Free Online Tool [2026]](/blog/fix-json-single-quotes)
- Fix Python JSON Errors: json.loads() Decode Errors and How to Repair Them
- Invalid JSON Meaning: What It Is and How to Fix It
- Why LLMs Output True Instead of true (and How to Fix It)
- Fix JSON SyntaxError: Unexpected Token
Key takeaways
- JSON allows only double quotes for keys and strings.
- json.loads() reports single quotes as "Expecting property name enclosed in double quotes" or "Expecting value".
- Printing a dict with str() produces Python syntax, not JSON. Use json.dumps().
- True, False and None need to become true, false and null.
- Use the Repair tool for text from APIs, files or LLMs, then confirm with the Validator.
FAQ
Does json.loads() accept single quotes if I set an option?
No. The json module has no option that turns on single-quote parsing. You need to fix the text first or parse it as a Python literal with ast.literal_eval().
Why does my printed dict fail in json.loads()?
Printing a dict uses its Python repr, which has single quotes and True, False and None. Use json.dumps(my_dict) to get valid JSON text.
Can I just replace ' with " in the string?
It works only for simple cases. It breaks on apostrophes inside values and leaves True, False and None unchanged. A repair tool or ast.literal_eval() handles these cases more reliably.
Does the JSON standard allow single quotes anywhere?
No. The standard defines strings and member names with double quotation marks. A single quote can appear inside a double-quoted string as an ordinary character.
Is ast.literal_eval() safe on untrusted input?
It does not run code like eval() does, but it can still use a lot of memory or time on very large or deeply nested input. Limit the input size before you call it.
Still dealing with broken JSON?
Paste it in and get it fixed in under 1 second — free, no signup, no install. Works with ChatGPT, Claude, n8n, and any AI output.
Fix My JSON Free →Related Articles