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.
Demo
import io, json buf = io.StringIO() json.dump({'name': 'Ada', 'tags': ['admin', 'dev']}, buf, indent=None) buf.getvalue()
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
| Name | Type | Required | Description |
|---|---|---|---|
| obj | any | yes | The data: dict, list, tuple, str, int, float, bool, None — anything else goes through default. |
| fp | text file | yes | 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. |
| indent | int | str | None | no (None) | Pretty-print with this many spaces (or this string) per level; None writes one line. |
| ensure_ascii | bool | no (True) | Escape non-ASCII as \uXXXX. With False the file contains the characters themselves — open it with encoding='utf-8'. |
| sort_keys | bool | no (False) | Write dict keys in sorted order. |
| separators | tuple[str, str] | no (None) | (item_separator, key_separator) — (',', ':') for the most compact file. |
| default | callable | no (None) | Converts objects json does not know (dates, sets, Decimal) into ones it does. |
| allow_nan | bool | no (True) | False raises ValueError for NaN and Infinity instead of writing them. |
| skipkeys | bool | no (False) | Drop dict keys of unsupported types instead of raising TypeError. |
| check_circular | bool | no (True) | Detect self-containing lists and dicts (ValueError). |
| cls | JSONEncoder subclass | no (None) | Encoder class to use. |
Return value
None — Nothing — the JSON goes into fp. Use json.dumps when you want the text.
Common patterns
import json with open('data.json', 'w', encoding='utf-8') as f: json.dump(data, f, indent=2, ensure_ascii=False)
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')
import json with open('events.jsonl', 'a', encoding='utf-8') as f: json.dump(event, f) f.write('\n')
Examples
Pitfalls
import json with open('out.json', 'wb') as f: json.dump({'a': 1}, f)
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
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
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')
import json text = json.dump({'a': 1})
import json text = json.dumps({'a': 1}) text
When to use
- 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
- 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
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.