JSON (JavaScript Object Notation) adalah format favorit pertukaran data di web: hampir semua API mengembalikan respons dalam JSON, berkas konfigurasi aplikasi memakainya, dan layanan penyimpanan dokumen seperti MongoDB menyimpan data dalam bentuk yang serupa. Berbeda dengan CSV yang selalu berupa tabel datar, JSON bersifat semi terstruktur: satu berkas bisa memuat list, object bersarang, dan campuran tipe dalam satu tempat. Method pd.read_json() menjembatani format fleksibel itu ke DataFrame yang rapi. Pada Chapter ini kita membaca JSON pertama, memahami konsep orientation yang menentukan bentuk teks JSON, dan mengenal varian JSON Lines yang lazim untuk log.

Dari JSON Sederhana ke DataFrame #

Bentuk JSON yang paling mudah diubah ke tabel adalah list of objects, yaitu list yang setiap elemennya adalah satu dictionary mewakili satu baris data. Bentuk inilah yang biasanya dikembalikan endpoint API. Skrip berikut menyusun data skor ujian tiga siswa, menyimpannya sebagai file JSON, lalu membacanya dengan read_json():

python
import json
import pandas as pd
from pathlib import Path

data = [
    {"nama": "Budi", "kota": "Bandung", "skor": 88},
    {"nama": "Siti", "kota": "Jakarta", "skor": 92},
    {"nama": "Dewi", "kota": "Surabaya", "skor": 79},
]
Path("skor.json").write_text(json.dumps(data, indent=2), encoding="utf-8")

df = pd.read_json("skor.json")
print(df)
print()
print(df.dtypes)

Path("skor.json").unlink()

Output yang Dihasilkan:

text
   nama      kota  skor
0  Budi   Bandung    88
1  Siti   Jakarta    92
2  Dewi  Surabaya    79

nama      str
kota      str
skor    int64
dtype: object

Mari kita uraikan:

  1. Baris 4-8 (data = [...]): data disusun sebagai list of dict; setiap dictionary punya key yang sama, yaitu nama, kota, dan skor.
  2. Baris 9 (json.dumps(data, indent=2)): modul bawaan json mengubah list Python menjadi teks JSON, dan Path.write_text() menyimpannya sebagai skor.json. Pada pekerjaan nyata, teks JSON ini biasanya datang dari respons API.
  3. Baris 11 (df = pd.read_json("skor.json")): pandas mengenali struktur list of objects, menjadikan setiap key sebagai nama kolom dan setiap object sebagai satu baris dengan index 0, 1, 2.
  4. Baris 12-14: output menampilkan tabel yang sudah rapi; kolom teks bertipe str dan kolom skor bertipe int64.

Argumen read_json() tidak harus berupa nama file. Path lokal, teks JSON yang dibungkus io.StringIO, dan URL dari API publik semuanya diterima; untuk contoh offline kita memakai file lokal, sementara di proyek nyata argumennya cukup diganti dengan URL endpoint. Detail parameter keduanya dijelaskan pada halaman read_json dan to_json .

Memahami Orientasi JSON #

Satu tabel yang sama bisa ditulis sebagai JSON dalam beberapa bentuk berbeda, dan bentuk itu disebut orientation. to_json() menyediakan parameter orient untuk memilih bentuknya, sedangkan read_json() perlu tahu bentuk tersebut agar bisa menyusun ulang tabel dengan benar. Dua orientasi yang paling sering ditemui:

OrientasiBentuk teks JSONKapan dipakai
columnsObject per kolom, berisi mapping index ke nilai (default to_json())Ekspor tabel utuh bersama index-nya
recordsList of objects, satu object per baris tanpa indexPertukaran data dengan API dan aplikasi lain
splitObject dengan key columns, index, dan data terpisahMenyimpan struktur tabel beserta index dan nama kolomnya

Skrip berikut mengekspor DataFrame log aktivitas dalam orientasi columns, membacanya kembali, lalu mengulanginya dengan orientasi records dan mode lines=True:

python
import pandas as pd
from pathlib import Path

log = pd.DataFrame({
    "waktu": ["2026-01-05 08:12", "2026-01-05 09:40"],
    "aktivitas": ["login", "checkout"],
    "pengguna": ["budi", "siti"],
})

log.to_json("orientasi.json", orient="columns", indent=2)
print(Path("orientasi.json").read_text(encoding="utf-8"))
print()

baca = pd.read_json("orientasi.json")
print(baca)
print()

log.to_json("orientasi.jsonl", orient="records", lines=True)
print(Path("orientasi.jsonl").read_text(encoding="utf-8"))

baca_baris = pd.read_json("orientasi.jsonl", lines=True)
print(baca_baris)

Path("orientasi.json").unlink()
Path("orientasi.jsonl").unlink()

Output yang Dihasilkan:

text
{
  "waktu":{
    "0":"2026-01-05 08:12",
    "1":"2026-01-05 09:40"
  },
  "aktivitas":{
    "0":"login",
    "1":"checkout"
  },
  "pengguna":{
    "0":"budi",
    "1":"siti"
  }
}

              waktu aktivitas pengguna
0  2026-01-05 08:12     login     budi
1  2026-01-05 09:40  checkout     siti

{"waktu":"2026-01-05 08:12","aktivitas":"login","pengguna":"budi"}
{"waktu":"2026-01-05 09:40","aktivitas":"checkout","pengguna":"siti"}

              waktu aktivitas pengguna
0  2026-01-05 08:12     login     budi
1  2026-01-05 09:40  checkout     siti

Hasil di atas memperlihatkan dua kebiasaan yang penting dicatat. Pertama, orientasi columns menyimpan index sebagai bagian dari struktur ("0", "1"), sehingga tabel bisa direkonstruksi persis; read_json() membentuknya kembali tanpa parameter tambahan. Kedua, orientasi records dengan lines=True menghasilkan satu baris teks per record tanpa index; mode ini disebut JSON Lines dan dibaca kembali dengan read_json("orientasi.jsonl", lines=True).

JSON Lines untuk Log dan Data Mengalir #

Format JSON Lines menyimpan setiap record sebagai satu baris teks yang berdiri sendiri, biasanya dengan ekstensi .jsonl. Struktur per baris ini membuat formatnya cocok untuk file log: aplikasi cukup menambahkan satu baris baru setiap ada kejadian, tanpa menulis ulang keseluruhan file. Kita juga bisa membaca file besar baris demi baris dengan parameter chunksize pada read_json(), sehingga memori tidak harus menampung seluruh file sekaligus. Ringkasan seluruh format baca-tulis, termasuk tabel lengkap orientasi JSON, tersedia pada halaman IO tools .

Posisi JSON dalam Alur Kerja Data #

Kita sudah bisa membawa data JSON ke dalam DataFrame, baik dari list of objects ala API maupun dari file JSON Lines. Dua sifatnya perlu selalu diingat: sangat fleksibel untuk struktur bersarang, tetapi tidak menyimpan dtype sehingga tipe data ditebak ulang setiap pembacaan. Untuk menyimpan tabel besar dengan tipe data utuh dan ukuran file kecil, format biner lebih tepat. Bila JSON respons API bersarang berlapis, pd.json_normalize() meratakannya menjadi tabel datar — bahasan Chapter berikutnya — sebelum kita lanjut ke Parquet, format kolom yang menjadi standar penyimpanan data analitik berukuran besar.