How to Convert a pandas DataFrame to JSON in Python

To convert a pandas DataFrame to JSON, call df.to_json(). The orient argument decides the shape: orient="records" gives the most common format, a JSON array with one object per row. Add indent=2 for readable output or a file path to save it. This guide compares every orient on the same DataFrame, then covers pretty printing, files and JSON Lines, dates, non-ASCII text and missing values, and reading the JSON back into a DataFrame.

All examples were run with Python 3.12.5 and pandas 3.0.6 in the Windows Command Prompt. Reference: DataFrame.to_json in the pandas documentation.

DataFrame to a JSON array

import pandas as pd

df = pd.DataFrame({
    "id": [101, 102, 103],
    "name": ["Anna", "Ben", "Chen"],
    "score": [91.5, 78.0, 85.25],
})

print(df.to_json(orient="records"))      # a JSON array: one object per row

Output:

[{"id":101,"name":"Anna","score":91.5},{"id":102,"name":"Ben","score":78.0},{"id":103,"name":"Chen","score":85.25}]

to_json orient options

The same three-row DataFrame, converted with each orient:

import pandas as pd

df = pd.DataFrame({
    "id": [101, 102, 103],
    "name": ["Anna", "Ben", "Chen"],
    "score": [91.5, 78.0, 85.25],
})

for orient in ["records", "columns", "index", "split", "values"]:
    print(f"{orient:<8}", df.to_json(orient=orient))

Output:

records  [{"id":101,"name":"Anna","score":91.5},{"id":102,"name":"Ben","score":78.0},{"id":103,"name":"Chen","score":85.25}]
columns  {"id":{"0":101,"1":102,"2":103},"name":{"0":"Anna","1":"Ben","2":"Chen"},"score":{"0":91.5,"1":78.0,"2":85.25}}
index    {"0":{"id":101,"name":"Anna","score":91.5},"1":{"id":102,"name":"Ben","score":78.0},"2":{"id":103,"name":"Chen","score":85.25}}
split    {"columns":["id","name","score"],"index":[0,1,2],"data":[[101,"Anna",91.5],[102,"Ben",78.0],[103,"Chen",85.25]]}
values   [[101,"Anna",91.5],[102,"Ben",78.0],[103,"Chen",85.25]]
Command Prompt output of a pandas DataFrame converted to JSON with orient records, columns, index, split and values
Five shapes of JSON from one DataFrame.
orientShapeGood for
records[{"id":101,...}, ...]APIs, JavaScript, most tools
columns (default){"id":{"0":101,...}, ...}Column-oriented storage
index{"0":{"id":101,...}, ...}Looking rows up by index
split{"columns":[...],"index":[...],"data":[...]}Compact, keeps column order
values[[101,"Anna",91.5], ...]Just the data
tableJSON Table Schema + dataKeeping dtypes and schema

Pretty-print with indent

import pandas as pd

df = pd.DataFrame({
    "id": [101, 102, 103],
    "name": ["Anna", "Ben", "Chen"],
    "score": [91.5, 78.0, 85.25],
})

print(df.to_json(orient="records", indent=2))     # readable, multi-line JSON

Output:

[
  {
    "id":101,
    "name":"Anna",
    "score":91.5
  },
  {
    "id":102,
    "name":"Ben",
    "score":78.0
  },
  {
    "id":103,
    "name":"Chen",
    "score":85.25
  }
]
Command Prompt output of pandas to_json with orient records and indent=2 printing each row as an indented JSON object
indent=2 makes the JSON readable.

pandas writes "id":101 without a space after the colon. If you need the exact formatting of json.dumps(), use the to_dict() route shown below.

Save a DataFrame as a JSON file (and JSON Lines)

Pass a path as the first argument. lines=True (with orient="records") writes JSON Lines, one object per line, which is easy to append to and to stream:

import os
import pandas as pd

df = pd.DataFrame({
    "id": [101, 102, 103],
    "name": ["Anna", "Ben", "Chen"],
    "score": [91.5, 78.0, 85.25],
})

df.to_json("scores.json", orient="records", indent=2)          # a normal JSON file
df.to_json("scores.jsonl", orient="records", lines=True)       # JSON Lines: one object per line

print(open("scores.jsonl").read())
print({name: os.path.getsize(name) for name in ["scores.json", "scores.jsonl"]}, "bytes")

Output:

{"id":101,"name":"Anna","score":91.5}
{"id":102,"name":"Ben","score":78.0}
{"id":103,"name":"Chen","score":85.25}

{'scores.json': 179, 'scores.jsonl': 114} bytes
Command Prompt output showing a pandas DataFrame saved as a JSON file and as a JSON Lines file with the contents and file sizes
A pretty JSON file and a compact JSON Lines file.

Dates, non-ASCII text and missing values

By default, datetimes become milliseconds since 1970 and non-ASCII characters are escaped. In pandas 3 this default also prints a Pandas4Warning saying the epoch format is deprecated, so pass date_format="iso" (and force_ascii=False for readable text). NaN is always written as null:

import numpy as np
import pandas as pd

df = pd.DataFrame({
    "city": ["São Paulo", "Zürich"],
    "joined": pd.to_datetime(["2025-07-04 09:30", "2025-08-15 14:00"]),
    "rating": [4.5, np.nan],
})

print(df.to_json(orient="records"))                                        # epoch milliseconds, \u escapes
print(df.to_json(orient="records", date_format="iso", force_ascii=False))  # ISO dates, real characters

Output:

C:\pyguides\dataframe_to_json_dates.py:10: Pandas4Warning: The default 'epoch' date format is deprecated and will be removed in a future version, please use 'iso' date format instead.
  print(df.to_json(orient="records"))                                        # epoch milliseconds, \u escapes
[{"city":"S\u00e3o Paulo","joined":1751621400000,"rating":4.5},{"city":"Z\u00fcrich","joined":1755266400000,"rating":null}]
[{"city":"São Paulo","joined":"2025-07-04T09:30:00.000","rating":4.5},{"city":"Zürich","joined":"2025-08-15T14:00:00.000","rating":null}]
Command Prompt output of pandas to_json with default epoch dates and escaped characters compared with date_format iso and force_ascii False, NaN written as null
Default output vs date_format="iso", force_ascii=False.

Build custom JSON with to_dict and json.dumps

When the JSON must match a specific structure (for example an API response with extra fields), convert to Python objects first:

import json
import pandas as pd

df = pd.DataFrame({
    "id": [101, 102, 103],
    "name": ["Anna", "Ben", "Chen"],
    "score": [91.5, 78.0, 85.25],
})

records = df.to_dict(orient="records")          # a list of Python dicts
print(records)
payload = json.dumps({"count": len(records), "results": records}, indent=2)   # wrap it in your own JSON
print(payload)

Output:

[{'id': 101, 'name': 'Anna', 'score': 91.5}, {'id': 102, 'name': 'Ben', 'score': 78.0}, {'id': 103, 'name': 'Chen', 'score': 85.25}]
{
  "count": 3,
  "results": [
    {
      "id": 101,
      "name": "Anna",
      "score": 91.5
    },
    {
      "id": 102,
      "name": "Ben",
      "score": 78.0
    },
    {
      "id": 103,
      "name": "Chen",
      "score": 85.25
    }
  ]
}

Read the JSON back into a DataFrame

from io import StringIO
import pandas as pd

df = pd.DataFrame({
    "id": [101, 102, 103],
    "name": ["Anna", "Ben", "Chen"],
    "score": [91.5, 78.0, 85.25],
})

text = df.to_json(orient="records")
df2 = pd.read_json(StringIO(text), orient="records")     # wrap literal JSON in StringIO
print(df2)
print("same data:", df.equals(df2))

Output:

    id  name  score
0  101  Anna  91.50
1  102   Ben  78.00
2  103  Chen  85.25
same data: True

Recent pandas versions warn when you pass a JSON string directly to read_json(); wrap it in StringIO or pass a file path.

Related pandas and conversion tutorials:

Frequently asked questions

How do I convert a pandas DataFrame to JSON?

Use df.to_json(orient="records") for a JSON array of row objects, or another orient for a different shape.

How do I convert a DataFrame to a JSON array?

df.to_json(orient="records") returns [{...}, {...}], one object per row.

How do I pretty-print DataFrame JSON?

Pass indent: df.to_json(orient="records", indent=2).

How do I save a DataFrame as a JSON file?

df.to_json("file.json", orient="records", indent=2); add lines=True for JSON Lines.

Why are my dates numbers in the JSON?

to_json writes datetimes as epoch milliseconds by default. Use date_format="iso".

How do I keep accented characters in the JSON?

Use force_ascii=False; otherwise characters like é are written as \u00e9.