Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Use Python’s built-in json module: json.loads() parses JSON text, json.load() reads JSON from a file-like object, json.dumps() turns a Python value into JSON text, and json.dump() writes JSON to a file-like object. The distinction is whether you have text or a stream, and whether you are reading or writing.

Choose the right JSON function

Function Direction Input or output Typical use
json.loads() JSON to Python JSON text as a string, bytes, or bytearray Parse an API response body already held in memory
json.load() JSON to Python Readable file-like object Read a JSON document from an open file
json.dumps() Python to JSON Python value in; JSON text string out Build JSON text to send or store
json.dump() Python to JSON Python value in; writes text to a file-like object Write a JSON document to an open file

All four functions are in the standard-library json module, so there is no third-party package to install.

Parse JSON text with loads()

Use loads() when the JSON document is already a Python string, such as text read from a network response or assembled elsewhere.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import json

raw = '{"name": "Ada", "active": true, "scores": [9, 10], "nickname": null}'
record = json.loads(raw)

print(record["name"])       # Ada
print(record["active"])     # True
print(record["scores"])     # [9, 10]
print(record["nickname"])   # None

The argument must contain a complete JSON document. In JSON, strings and object keys use double quotes; Python-style single-quoted strings are not valid JSON. JSON’s true, false, and null become Python’s True, False, and None.

Read a JSON file with load()

Use load() with an open text file. Open the file with an explicit encoding so the text is decoded consistently.

import json

with open("data.json", "r", encoding="utf-8") as file:
    record = json.load(file)

print(record)

load() reads from a file-like object with a read() method. The same distinction applies to other readable streams: it is the stream, rather than a string containing JSON, that you pass to load().

Read bytes when necessary

loads() also accepts bytes and bytearray. For byte input, the JSON module supports UTF-8, UTF-16, and UTF-32. If you read a file as bytes yourself, use the expected encoding when decoding it, or pass the bytes directly to loads(). An incompatible byte encoding may raise UnicodeDecodeError, which is different from malformed JSON.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Write JSON text or a JSON file

Use dumps() when you need the encoded text as a Python string. Use dump() when you want to write to a text file or another file-like object whose write() method accepts strings.

import json

record = {"name": "Ada", "active": True, "scores": [9, 10], "nickname": None}

# Return JSON text as a Python str
text = json.dumps(record, indent=2)
print(text)

# Write one JSON document to a UTF-8 text file
with open("data.json", "w", encoding="utf-8") as file:
    json.dump(record, file, indent=2)

Both examples produce valid JSON. The indented form is easier for people to inspect; compact output may be more convenient when you need a short string. dumps() returns a Python str, not bytes. If a later interface requires bytes, encode that string using the encoding expected by that interface.

Know which Python values JSON represents

Parsing converts JSON values to ordinary Python types. The default mapping is useful to know when accessing the result:

JSON value Python value
object dict (with string keys)
array list
string str
number int or float
true / false True / False
null None

JSON does not define Python-specific values such as sets, dates, or arbitrary class instances. Before encoding one, choose a representation that your application and any receiving system understand—for example, a date string in a documented format—and convert it explicitly.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Format output and customize conversions

Make output readable or consistent

  • indent=2 (or another indentation level) adds whitespace and line breaks for readability.
  • sort_keys=True writes object keys in sorted order, which can help when comparing output or producing stable displays.
  • ensure_ascii=False emits non-ASCII characters directly instead of escaping them. The result is still a Python string; choose the correct encoding when writing it.
  • allow_nan=False makes encoding reject NaN and infinities instead of emitting those non-standard JSON values.
import json

record = {"city": "Zürich", "value": 12}
text = json.dumps(
    record,
    ensure_ascii=False,
    sort_keys=True,
    indent=2,
    allow_nan=False,
)
print(text)

Convert unsupported values deliberately

Pass a default callable to dump() or dumps() when you want to define how otherwise unsupported values should be represented. Make the representation explicit rather than assuming JSON can preserve the original Python type.

import json
from datetime import date

def encode_special(value):
    if isinstance(value, date):
        return value.isoformat()
    raise TypeError(f"Cannot serialize {type(value).__name__}")

text = json.dumps({"created": date(2026, 9, 29)}, default=encode_special)
print(text)  # {"created": "2026-09-29"}

The receiving application gets a string; it does not automatically recover a date object. Define and apply a corresponding decoding rule if you need that conversion. Raising TypeError for unhandled types also prevents an accidental, misleading representation.

Customize decoding

Decoding hooks can change how values are constructed. For example, parse_float can preserve decimal precision by using decimal.Decimal, while object_hook can transform each decoded JSON object (dictionary) into an application-specific representation.

import json
from decimal import Decimal

value = json.loads('{"price": 0.10}', parse_float=Decimal)
print(value["price"])        # Decimal('0.10')
print(type(value["price"]))  # <class 'decimal.Decimal'>

Choose hooks because the application needs their behavior, not just to make parsing succeed. For example, a Decimal value is not among the JSON module’s ordinary output types; if you later encode it, provide a deliberate conversion.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Handle malformed input and encoding errors

Malformed JSON raises json.JSONDecodeError, which is a ValueError subclass. Its line and column fields help locate the problem in the input.

import json

raw_text = '{"name": "Ada",}'
try:
    data = json.loads(raw_text)
except json.JSONDecodeError as exc:
    print(f"Invalid JSON at line {exc.lineno}, column {exc.colno}: {exc.msg}")

Catch this specific error when invalid external input is an expected possibility. Avoid replacing it with a blanket exception handler that hides unrelated programming or I/O failures.

Common causes and fixes

  • Single quotes: JSON strings and keys require double quotes. Supply valid JSON rather than a Python representation such as {'name': 'Ada'}.
  • Trailing comma: Remove the comma before a closing } or ].
  • Missing separator or bracket: Check commas between members or array items and make sure every opening delimiter has a matching close.
  • Empty or non-JSON response: Inspect the actual input before parsing. An empty response, an HTML error page, or other content is not a JSON document, even if it came from an endpoint you expected to return JSON.
  • UnicodeDecodeError: This points to byte decoding, not necessarily invalid JSON syntax. Check how bytes were encoded and read them as UTF-8, UTF-16, or UTF-32 as appropriate.
  • Wrong shape after parsing: A valid document can decode to a list, string, number, boolean, or None, not just a dictionary. Check the structure before using dictionary indexing.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Avoid common writing and round-trip pitfalls

Do not concatenate independent documents with repeated dumps

JSON is not a framed protocol. Calling dump() repeatedly on the same file does not automatically add separators or create a valid sequence of independent JSON documents. For one JSON file, write one enclosing value—often a list—or define a separate line-oriented format and parse each line according to that format.

Dictionary keys may change in a round trip

JSON object keys are strings. When Python encodes a dictionary, non-string keys are coerced to strings. Consequently, json.loads(json.dumps(value)) is not guaranteed to equal value if it has non-string dictionary keys. Use string keys when the data is intended to round-trip through JSON without that change.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Reject non-standard numeric values when needed

Python can encounter values such as float("nan") or infinity. If the output must be strict JSON, set allow_nan=False so these values produce an error that you can handle, rather than emitting representations that are not standard JSON.

Validate and pretty-print JSON from a terminal

To check JSON supplied on standard input and print it in a readable form, run:

python -m json < data.json

This is a quick syntax check and formatter for a document in a file. If the command reports an error, inspect the input around the reported location; the command does not turn Python literals into JSON or repair malformed input automatically.

Or skip the browser setup

If your workflow also needs a website screenshot, ScreenshotNeo provides a screenshot API; it is a separate task from parsing JSON with Python. One GET request can return a screenshot or PDF. The API response includes headers indicating the page verdict and whether the request was billed.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
open("shot.webp", "wb").write(r.content)

See the ScreenshotNeo API documentation for request parameters. Cookie banners, popups, and chat widgets are removed before the shot; bot checks, blank pages, and failed loads are never billed. An MCP server lets AI agents take screenshots. The Free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000. Learn about ScreenshotNeo or sign up for 1,000 free screenshots a month with no card.

Frequently Asked Questions

Can I parse JSON without installing a package?

Yes. Python’s standard-library json module is included with Python, so no separate JSON package is needed.

Does json.loads() accept a URL?

No. It accepts JSON text or bytes, not a URL. Retrieve the response body with an HTTP client first, then pass the response text or bytes to the JSON decoder.

Can I parse several JSON documents from one file with json.load()?

An ordinary JSON document contains one top-level value. A sequence of documents needs an explicitly defined framing convention; repeated dumps alone do not supply one.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.