The essentials
Quick reference
One focused task per row. Jump to the related section for complete, working examples.
| Use | Syntax | Examples |
|---|---|---|
| Encode a JSON string | text = json.dumps(value) | View examples |
| Decode a JSON string | value = json.loads(text) | View examples |
| Use interoperable value types | payload = {'ok': True, 'items': [1, 2], 'note': None} | View examples |
| Pretty-print deterministically | text = json.dumps(value, indent=2, sort_keys=True, ensure_ascii=False) | View examples |
| Emit compact JSON | text = json.dumps(value, separators=(',', ':'), ensure_ascii=False) | View examples |
| Encode to a text stream | json.dump(value, stream) | View examples |
| Decode from a stream | value = json.load(stream) | View examples |
| Encode a custom type | text = json.dumps(value, default=encode_custom) | View examples |
| Transform decoded objects | value = json.loads(text, object_hook=decode_custom) | View examples |
| Parse decimals exactly | value = json.loads(text, parse_float=Decimal) | View examples |
| Reject non-finite output | text = json.dumps(value, allow_nan=False) | View examples |
| Inspect object key pairs | value = json.loads(text, object_pairs_hook=reject_duplicates) | View examples |
| Read CSV rows | rows = csv.reader(stream, delimiter=',') | View examples |
| Write CSV rows | writer = csv.writer(stream, lineterminator='\n') | View examples |
| Read named CSV fields | rows = csv.DictReader(stream) | View examples |
| Write named CSV fields | writer = csv.DictWriter(stream, fieldnames=['name', 'note']) | View examples |
JSON and CSV are interchange formats, not snapshots of arbitrary Python objects. Define the wire shape, encoding, numeric policy, and CSV dialect at each boundary; validate untrusted input before trusting its contents; and make output deterministic when it will be tested, reviewed, cached, or signed. The standard library handles syntax, while your application remains responsible for schemas, size limits, and domain validation.
Step by step
Detailed examples
Translate deliberately between Python and JSON values
JSON objects, arrays, strings, numbers, booleans, and null map naturally to Python dictionaries, lists, strings, integers or floats, booleans, and None. Tuples encode as arrays and decode as lists, while JSON object names are strings, so a round trip can change tuple identity and non-string dictionary keys. JSON does not natively represent Decimal, datetime, sets, bytes, or arbitrary instances. Treat decoding as parsing rather than validation, and limit the byte size and nesting of untrusted documents before or around parsing.
import json
payload = {'active': True, 'tags': ('api', 'batch'), 'missing': None}
encoded = json.dumps(payload, sort_keys=True, separators=(',', ':'))
decoded = json.loads(encoded)
print(encoded)
print(type(decoded['tags']).__name__)
print(type(decoded['missing']).__name__) {"active":true,"missing":null,"tags":["api","batch"]}
list
NoneTypeChoose readable, compact, and Unicode output intentionally
indent makes nested data readable; separators controls optional whitespace; and sort_keys stabilizes object member order for tests and review. Since Python dictionaries preserve insertion order, default encoding also preserves their order, but that is not a canonicalization scheme for signatures. ensure_ascii=False keeps non-ASCII characters readable in the returned str; encode that text as UTF-8 at the byte boundary. These presentation options do not validate a schema or normalize numbers and Unicode for cryptographic canonicalization.
import json
record = {'count': 2, 'city': 'São Paulo'}
pretty = json.dumps(record, indent=2, sort_keys=True, ensure_ascii=False)
compact = json.dumps(record, sort_keys=True, ensure_ascii=False, separators=(',', ':'))
print(pretty)
print(compact) {
"city": "São Paulo",
"count": 2
}
{"city":"São Paulo","count":2}Keep document framing separate from stream I/O
dump and load operate on file-like objects, whereas dumps and loads return or accept in-memory values. The encoder writes str, so a destination must accept text. JSON is not a framed protocol: repeated dump calls to one stream concatenate values into invalid single-document JSON. For multiple messages, use a specified envelope, a length-prefixed protocol, or a documented format such as newline-delimited JSON with one compact value per physical line.
import json
from io import StringIO
source = StringIO('{"items": [3, 1, 2]}')
document = json.load(source)
document['items'].sort()
destination = StringIO()
json.dump(document, destination, separators=(',', ':'))
print(destination.getvalue()) {"items":[1,2,3]}Tag custom representations and reject unknown objects
The default callback handles values the built-in encoder cannot serialize. Return only JSON-compatible data and raise TypeError for unsupported values instead of silently converting everything to strings. object_hook receives every decoded object from the inside out; use an explicit, versioned tag and validate all required fields before reconstructing a domain value. Never treat a tag from untrusted input as permission to import a class or execute code.
import json
from decimal import Decimal
def encode_custom(value):
if isinstance(value, Decimal):
return {'$type': 'decimal', 'value': str(value)}
raise TypeError(f'unsupported type: {type(value).__name__}')
def decode_custom(value):
if value.get('$type') == 'decimal' and set(value) == {'$type', 'value'}:
return Decimal(value['value'])
return value
encoded = json.dumps({'price': Decimal('79.90')}, default=encode_custom, sort_keys=True)
decoded = json.loads(encoded, object_hook=decode_custom)
print(encoded)
print(decoded['price'] + Decimal('0.10')) {"price": {"$type": "decimal", "value": "79.90"}}
80.00Make numeric and object-name policies explicit
parse_float can preserve decimal text as Decimal when binary floating-point rounding is inappropriate. Python accepts and emits NaN and infinities by default even though strict JSON does not; set allow_nan=False when encoding and use parse_constant to reject them while decoding. Duplicate object names keep only the last value by default. An object_pairs_hook can reject duplicates before information is discarded. None of these controls replaces application-level limits or schema validation.
import json
from decimal import Decimal
def reject_duplicates(pairs):
result = {}
for key, value in pairs:
if key in result:
raise ValueError(f'duplicate key: {key}')
result[key] = value
return result
amounts = json.loads('{"subtotal": 0.1, "tax": 0.2}', parse_float=Decimal)
print(amounts['subtotal'] + amounts['tax'])
operations = (
('non-finite number', lambda: json.dumps(float('nan'), allow_nan=False)),
('duplicate key', lambda: json.loads('{"role": "user", "role": "admin"}', object_pairs_hook=reject_duplicates)),
)
for label, operation in operations:
try:
operation()
except ValueError:
print(f'rejected: {label}') 0.3
rejected: non-finite number
rejected: duplicate keyTreat a CSV dialect as part of the contract
CSV has families of dialects rather than one universal interpretation. Declare delimiters, quoting, escape behavior, and line endings when the producer and consumer contract requires them. Open real CSV files with newline='' so the csv module controls newline processing correctly. Readers normally return strings and do not validate columns or convert domain types. DictReader and DictWriter make column names explicit; configure extrasaction and validate missing, extra, oversized, or formula-like fields according to the downstream system.
import csv
from io import StringIO
rows = [
{'name': 'Ada', 'note': 'uses, commas'},
{'name': 'Lin', 'note': 'line one\nline two'},
]
buffer = StringIO(newline='')
writer = csv.DictWriter(buffer, fieldnames=['name', 'note'], lineterminator='\n')
writer.writeheader()
writer.writerows(rows)
print(repr(buffer.getvalue()))
buffer.seek(0)
loaded = list(csv.DictReader(buffer))
print(loaded) 'name,note\nAda,"uses, commas"\nLin,"line one\nline two"\n'
[{'name': 'Ada', 'note': 'uses, commas'}, {'name': 'Lin', 'note': 'line one\nline two'}]Local code tester
Explore JSON and CSV interchange
Encode a deterministic JSON document and round-trip CSV records entirely in memory.
Press Run to load Python locally.
Sources and further reading
References
Authoritative documentation used to verify and expand this cheat sheet.
- Python Software Foundationjson — JSON encoder and decoderdocs.python.org
- Python Software Foundationcsv — CSV File Reading and Writingdocs.python.org
- Python Software Foundationio — Core tools for working with streamsdocs.python.org
- Python Software Foundationdecimal — Decimal fixed-point and floating-point arithmeticdocs.python.org
Help us improve
Found a typo or missing example?
Tell us what would make this cheat sheet clearer, more complete, or more useful.



