True, False and None are not JSON: Unexpected token 'T' or 'N'

JSON spells its literals in lower case: true, false and null. Python spells them True, False and None, so text produced by printing a Python object (rather than serializing it) fails at the first capital letter. The data is fine; it was just written in Python syntax. Fix it in PasteKit converts the literals, and switching to json.dumps stops it happening again.

Seen as:

  • SyntaxError: Unexpected token 'T', ...""active": True, "m"... is not valid JSON
  • SyntaxError: Unexpected token T in JSON at position 31
  • SyntaxError: JSON.parse: unexpected character at line 3 column 13 of the JSON data
  • SyntaxError: JSON Parse error: Unexpected identifier "True"
  • json.decoder.JSONDecodeError: Expecting value: line 3 column 13 (char 31)

Input

Settings

History

Load from URL

Common causes

1. print() or str() on a dict

Printing a dict shows its Python representation, not JSON. Besides the capitalised literals it also uses single quotes. Serialize with json.dumps.

Before
logger.info("payload=%s", payload)
After
logger.info("payload=%s", json.dumps(payload))

2. JSON built with an f-string

Formatting a bool into a string gives True, and None gives None. Let the serializer translate Python values into JSON values.

Before
body = f'{{"user": "{user}", "active": {active}, "manager": {manager}}}'
After
body = json.dumps({"user": user, "active": active, "manager": manager})

3. Jinja or Ansible templates rendering Python values

In a Jinja template, {{ enabled }} renders a Python bool as True. Use the tojson filter ({{ enabled | tojson }}) so the rendered file contains true.

Before
{"enabled": True, "replicas": 3, "owner": None}
After
{"enabled": true, "replicas": 3, "owner": null}

4. Converting a value that is already a dict

Calling json.loads(str(data)) on data that is already a dict fails on the quotes and literals. If you have the object, use it directly; if you need a copy, use copy.deepcopy.

Before
config = json.loads(str(response_data))
After
config = response_data

Frequently asked questions

Why does Python not write JSON when I print a dict?

print calls repr-style formatting meant for Python developers. It happens to look like JSON for simple data, but differs in quotes, literals and in values such as tuples or datetimes. Only json.dumps guarantees JSON output.

Can I parse Python-style text in Python?

Yes: ast.literal_eval safely evaluates a dict literal written with True, None and single quotes. Use it to recover existing data, then save it with json.dumps.

Does Fix it handle single quotes too?

Yes. Python dict output usually has both problems, and Fix it converts single quotes and True, False and None in one pass, showing every change as a diff.

Related