json.dump

Writes JSON into anything with a write() method, piece by piece as it is produced — which is why an error half-way leaves half a file behind.

json functionPython 2.6+Live demo
Common call
json.dump(data, f, indent=2, ensure_ascii=False)
Returns
None — the JSON is in the file
Replaces
f.write(json.dumps(data))
Watch out
open the file in text mode ('w', encoding='utf-8'), not 'wb'
json.dump(objobj — The data: dict, list, tuple, str, int, float, bool, None — anything else goes through default.type: any · required, fpfp — Any object with a write(str) method: a file opened with 'w' or 'a', io.StringIO, sys.stdout. A binary file ('wb') raises TypeError on the first write.type: text file · required, *, skipkeysskipkeys — Drop dict keys of unsupported types instead of raising TypeError.type: bool · default: False=False, ensure_asciiensure_ascii — Escape non-ASCII as \uXXXX. With False the file contains the characters themselves — open it with encoding='utf-8'.type: bool · default: True=True, check_circularcheck_circular — Detect self-containing lists and dicts (ValueError).type: bool · default: True=True, allow_nanallow_nan — False raises ValueError for NaN and Infinity instead of writing them.type: bool · default: True=True, clscls — Encoder class to use.type: JSONEncoder subclass · default: None=None, indentindent — Pretty-print with this many spaces (or this string) per level; None writes one line.type: int | str | None · default: None=None, separatorsseparators — (item_separator, key_separator) — (',', ':') for the most compact file.type: tuple[str, str] · default: None=None, defaultdefault — Converts objects json does not know (dates, sets, Decimal) into ones it does.type: callable · default: None=None, sort_keyssort_keys — Write dict keys in sorted order.type: bool · default: False=False, **kw)
→ None

Demo

Live evaluation
io.StringIO is an in-memory text file — getvalue() shows exactly what a real file would contain.
Try:
Inputs
namestrany text
tagslist[str]comma-separated
indentint | Nonespaces, empty = None
Code
import io, json
buf = io.StringIO()
json.dump({'name': 'Ada', 'tags': ['admin', 'dev']}, buf, indent=None)
buf.getvalue()
Result
'{"name": "Ada", "tags": ["admin", "dev"]}'

With indent=2 the file gets one item per line and no newline at the very end — dump never adds one. In "write() calls", a dict is written key, ": ", value and ", " as separate pieces, while each list item travels together with the [ or ", " in front of it — ["admin" is one write, , "dev" the next. In "error half-way", the file ends right after "seen": — the key was written before json found out it could not write the value.

Parameters

NameTypeRequiredDescription
objanyyesThe data: dict, list, tuple, str, int, float, bool, None — anything else goes through default.
fptext fileyesAny object with a write(str) method: a file opened with 'w' or 'a', io.StringIO, sys.stdout. A binary file ('wb') raises TypeError on the first write.
indentint | str | Noneno (None)Pretty-print with this many spaces (or this string) per level; None writes one line.
ensure_asciiboolno (True)Escape non-ASCII as \uXXXX. With False the file contains the characters themselves — open it with encoding='utf-8'.
sort_keysboolno (False)Write dict keys in sorted order.
separatorstuple[str, str]no (None)(item_separator, key_separator) — (',', ':') for the most compact file.
defaultcallableno (None)Converts objects json does not know (dates, sets, Decimal) into ones it does.
allow_nanboolno (True)False raises ValueError for NaN and Infinity instead of writing them.
skipkeysboolno (False)Drop dict keys of unsupported types instead of raising TypeError.
check_circularboolno (True)Detect self-containing lists and dicts (ValueError).
clsJSONEncoder subclassno (None)Encoder class to use.

Return value

None — Nothing — the JSON goes into fp. Use json.dumps when you want the text.

Common patterns

Write a JSON file
Text mode with an explicit encoding, so non-ASCII output is portable.
import json
with open('data.json', 'w', encoding='utf-8') as f:
    json.dump(data, f, indent=2, ensure_ascii=False)
Never leave a broken file behind
Serialize first, then write to a temporary file and swap it in — the old file survives any error.
import json, os
text = json.dumps(data, indent=2)
with open('data.json.tmp', 'w', encoding='utf-8') as f:
    f.write(text)
os.replace('data.json.tmp', 'data.json')
Append records as JSON Lines
One JSON document per line — appendable, streamable, and every line parses on its own.
import json
with open('events.jsonl', 'a', encoding='utf-8') as f:
    json.dump(event, f)
    f.write('\n')

Examples

1. Write, then read the file
import json with open('out.json', 'w', encoding='utf-8') as f: json.dump({'a': [1, 2]}, f) with open('out.json', encoding='utf-8') as f: text = f.read() text
Returns
'{"a": [1, 2]}'
2. dump returns None
import io, json result = json.dump({'a': 1}, io.StringIO()) result is None
Returns
True
3. Pretty and non-ASCII
import json with open('city.json', 'w', encoding='utf-8') as f: json.dump({'city': 'Zürich', 'zip': ['8001']}, f, indent=2, ensure_ascii=False) with open('city.json', encoding='utf-8') as f: lines = f.read().splitlines() lines
Returns
['{', ' "city": "Zürich",', ' "zip": [', ' "8001"', ' ]', '}']
4. No trailing newline
import io, json buf = io.StringIO() json.dump([1], buf) buf.getvalue()
Returns
'[1]'
5. JSON Lines: one per line
import json with open('log.jsonl', 'a', encoding='utf-8') as f: for event in [{'id': 1}, {'id': 2}]: json.dump(event, f) f.write('\n') with open('log.jsonl', encoding='utf-8') as f: lines = f.read().splitlines() lines
Returns
['{"id": 1}', '{"id": 2}']
6. Straight to stdout
import json, sys json.dump({'ok': True}, sys.stdout)
Returns
{"ok": true}
7. A file name is not a file
import json json.dump({'a': 1}, 'out.json')
Returns
AttributeError: 'str' object has no attribute 'write'

Pitfalls

1. Opening the file in binary mode
dump writes str, so the file must be opened in text mode. 'wb' fails on the first write.
'wb'
import json
with open('out.json', 'wb') as f:
    json.dump({'a': 1}, f)
TypeError: a bytes-like object is required, not 'str'
'w', encoding='utf-8'
import json
with open('out.json', 'w', encoding='utf-8') as f:
    json.dump({'a': 1}, f)
with open('out.json', encoding='utf-8') as f:
    text = f.read()
text
'{"a": 1}'
2. A half-written file after an error
dump writes as it encodes. When it meets something it cannot serialize, the part before is already in the file — and the old content is gone, because opening with 'w' emptied it.
dump into the file
import json
try:
    with open('out.json', 'w', encoding='utf-8') as f:
        json.dump({'id': 7, 'tags': {'a'}}, f)
except TypeError:
    pass
with open('out.json', encoding='utf-8') as f:
    text = f.read()
text
'{"id": 7, "tags": '
dumps first, then write
import json, os
try:
    text = json.dumps({'id': 7, 'tags': {'a'}})
    with open('out.json', 'w', encoding='utf-8') as f:
        f.write(text)
except TypeError:
    pass
os.path.exists('out.json')
False
3. Expecting a string back
dump needs a file and returns None. For the JSON text, use dumps.
json.dump(x)
import json
text = json.dump({'a': 1})
TypeError: dump() missing 1 required positional argument: 'fp'
json.dumps(x)
import json
text = json.dumps({'a': 1})
text
'{"a": 1}'

When to use

Use it
  • Saving data, config or results to a .json file
  • Writing to any text stream — sys.stdout, a socket wrapper, io.StringIO
  • Appending JSON Lines records, one dump plus a newline each
Reach for something else
  • You need the text itself → json.dumps
  • The data might not serialize and a broken file would hurt → json.dumps first, then write
  • Binary streams → write json.dumps(data).encode() instead

Notes

CPython impl
Lib/json/__init__.py: dump iterates JSONEncoder(...).iterencode(obj) and calls fp.write(chunk) for every chunk — the pure-Python encoder, never the one-shot C path dumps uses
Output
Exactly what dumps would return for the same arguments; no trailing newline
Encoding
With ensure_ascii=True (the default) the output is pure ASCII; with False, the file's encoding matters — pass encoding='utf-8' to open()

FAQ

Open the file in text mode and pass it to dump: with open('data.json', 'w', encoding='utf-8') as f: json.dump(data, f, indent=2). Use ensure_ascii=False if you want non-ASCII characters written as they are.