JSON

Struktur JSON bersarang beserta strategi perataan untuk mengubahnya menjadi tabel analitik.

Daftar isi

JSON adalah format data berbasis teks yang menjadi bahasa bersama API, berkas konfigurasi, dan pesan antar layanan. Strukturnya dapat bersarang beberapa tingkat, sedangkan tabel analitik menuntut bentuk datar dengan kolom yang tetap. Topik ini membahas anatomi JSON bersarang beserta strategi perataan yang mengubahnya menjadi tabel analitik, dengan dua pendekatan yang dijalankan langsung pada berkas contoh.

Struktur dasar JSON#

JSON membangun data dari dua struktur. Object adalah kumpulan pasangan kunci dan nilai yang ditulis di dalam kurung kurawal, sementara array adalah daftar nilai berurutan yang ditulis di dalam kurung siku. Nilai atomiknya terbatas pada string, bilangan, boolean, dan null, sedangkan object dan array boleh saling berisi tanpa batas kedalaman yang ditegakkan formatnya. Kebebasan ini yang membuat JSON nyaman dipakai untuk data yang bentuknya tidak seragam, tetapi juga yang membuatnya tidak dapat langsung dimuat sebagai tabel.

Berkas berikut memuat dua pesanan dengan sarang dua tingkat, yaitu object pelanggan dan array item di dalam setiap pesanan.

json pesanan.json
[
  {
    "id_pesanan": "PSN-1042",
    "tanggal": "2026-01-12",
    "pelanggan": {
      "nama": "Dewi",
      "kota": "Bandung"
    },
    "item": [
      {"nama": "Buku Tulis", "harga": 8500, "jumlah": 4},
      {"nama": "Pensil 2B", "harga": 3000, "jumlah": 10}
    ]
  },
  {
    "id_pesanan": "PSN-1043",
    "tanggal": "2026-01-13",
    "pelanggan": {
      "nama": "Ali",
      "kota": "Surabaya"
    },
    "item": [
      {"nama": "Penghapus", "harga": 2500, "jumlah": 2}
    ]
  }
]

Tingkat pertama adalah pesanan itu sendiri dengan kunci id_pesanan dan tanggal. Tingkat kedua berada di dalamnya, yaitu object pelanggan yang memuat nama dan kota, serta array item yang setiap anggotanya memuat nama, harga, dan jumlah. Kedalaman seperti ini wajar pada data nyata, dan keduanya harus diurai dengan aturan yang tegas sebelum masuk ke tabel.

Perataan menjadi tabel analitik#

Tabel analitik menuntut setiap baris berbentuk datar dengan kolom yang sama, sehingga struktur bersarang perlu diratakan (flatten), yakni diubah menjadi satu tingkat kunci tanpa sarang. Aturan yang lazim dipakai berbunyi seperti ini. Object bersarang dijadikan kolom baru dengan nama gabungan, misalnya pelanggan.kota menjadi kolom pelanggan_kota. Array of object dijadikan baris baru, yaitu setiap anggota array menghasilkan satu baris tabel sambil memuat ulang kunci induknya.

Diterapkan pada pesanan.json, aturan tersebut menghasilkan tiga baris karena pesanan pertama memuat dua item dan pesanan kedua memuat satu item. Kunci id_pesanan, tanggal, dan pelanggan diulang pada setiap baris itemnya. Tabel hasil berada pada tingkat item, sedangkan informasi pesanan tersebar di setiap barisnya.

Pengulangan kunci induk menunjukkan perubahan tingkat detail data. Agregasi yang dirancang untuk tingkat pesanan perlu berhati-hati agar tidak menjumlahkan nilai pesanan dua kali ketika pesanannya memiliki lebih dari satu item. Aturan perataan karenanya harus dipilih sesuai pertanyaan analitik yang akan dijawab, bukan sekadar mengikuti bentuk asli berkasnya.

Perataan dengan perulangan murni#

Versi perulangan murni membuat setiap keputusan perataan terlihat eksplisit, sehingga cocok untuk memahami mekanismenya sebelum memakai pustaka.

python ratakan.py
import json

with open("pesanan.json", encoding="utf-8") as f:
    data = json.load(f)

# ratakan: object bersarang menjadi kolom, array item menjadi baris
kolom = ["id_pesanan", "tanggal", "pelanggan", "kota", "item", "harga", "jumlah"]
baris = []
for pesanan in data:
    for item in pesanan["item"]:
        baris.append({
            "id_pesanan": pesanan["id_pesanan"],
            "tanggal": pesanan["tanggal"],
            "pelanggan": pesanan["pelanggan"]["nama"],
            "kota": pesanan["pelanggan"]["kota"],
            "item": item["nama"],
            "harga": item["harga"],
            "jumlah": item["jumlah"],
        })

# cetak tabel dengan lebar kolom mengikuti isi terpanjang
lebar = {k: max(len(k), *(len(str(b[k])) for b in baris)) for k in kolom}
print("  ".join(k.ljust(lebar[k]) for k in kolom))
for b in baris:
    print("  ".join(str(b[k]).ljust(lebar[k]) for k in kolom))
text Keluaran
id_pesanan  tanggal     pelanggan  kota      item        harga  jumlah
PSN-1042    2026-01-12  Dewi       Bandung   Buku Tulis  8500   4     
PSN-1042    2026-01-12  Dewi       Bandung   Pensil 2B   3000   10    
PSN-1043    2026-01-13  Ali        Surabaya  Penghapus   2500   2     

Perulangan luar berjalan satu kali per pesanan, lalu perulangan dalam berjalan satu kali per item, sehingga satu pesanan dengan dua item menghasilkan dua baris. Akses pesanan["pelanggan"]["kota"] menuruni dua tingkat object sekaligus dan mengambil nilai tingkat kedua. Tabel yang dicetak menampilkan tiga baris dengan kunci induk yang diulang, persis seperti uraian aturan pada bagian sebelumnya.

Perataan dengan json_normalize#

pandas menyediakan json_normalize yang menerapkan aturan perataan tersebut tanpa perulangan yang ditulis sendiri.

python ratakan-pandas.py
import json

import pandas as pd

with open("pesanan.json", encoding="utf-8") as f:
    data = json.load(f)

df = pd.json_normalize(
    data,
    record_path="item",
    meta=["id_pesanan", "tanggal", ["pelanggan", "nama"], ["pelanggan", "kota"]],
    sep="_",
)
df = df.rename(columns={"nama": "item", "pelanggan_nama": "pelanggan", "pelanggan_kota": "kota"})
df = df[["id_pesanan", "tanggal", "pelanggan", "kota", "item", "harga", "jumlah"]]
print(df.to_string(index=False))
text Keluaran
id_pesanan    tanggal pelanggan     kota       item  harga  jumlah
  PSN-1042 2026-01-12      Dewi  Bandung Buku Tulis   8500       4
  PSN-1042 2026-01-12      Dewi  Bandung  Pensil 2B   3000      10
  PSN-1043 2026-01-13       Ali Surabaya  Penghapus   2500       2

Parameter record_path menunjuk array yang dijadikan baris, parameter meta menunjuk kunci induk yang diulang, dan sep menentukan pemisah nama kolom hasil gabungan. Dua kolom hasil gabungan diganti namanya agar sama persis dengan versi perulangan murni, dan urutan kolomnya diatur ulang secara eksplisit. Keluaran keduanya identik untuk data ini, dan kesamaan itu menjadi bukti bahwa aturan perataan yang sama dapat ditulis dalam dua bentuk.

Untuk berkas yang jauh lebih besar, json_normalize lebih ringkas dan lebih teruji karena ditangani pustaka, sedangkan perulangan murni tetap berguna saat aturan perataannya tidak standar. Contoh kondisi terakhir adalah nilai yang perlu diubah bentuknya di tengah proses, misalnya tanggal yang formatnya berbeda antar record. Pilih bentuk yang paling jelas membaca maksudnya, dan konsistenkan pilihan itu di seluruh pipeline.

Kesalahan umum#

Kesalahan berikut sering muncul saat JSON diubah menjadi tabel, dan ketiganya dapat dicegah dengan asumsi yang dinyatakan lebih dahulu.

  • Mengasumsikan semua record memuat kunci yang sama. Akses langsung dengan kurung siku memicu KeyError pada data yang kuncinya tidak lengkap. Perbaikannya adalah menggunakan .get() dengan nilai bawaan untuk kunci yang opsional.
  • Menggabungkan array skalar menjadi satu string, misalnya dengan pemisah garis tegak. Nilainya sulit diquery kembali dan mudah rusak apabila pemisahnya muncul di dalam data. Perbaikannya adalah menjadikan array sebagai baris terpisah bila isinya perlu dianalisis.
  • Memuat JSON bersarang apa adanya ke satu kolom di warehouse. Query menjadi bergantung pada fungsi ekstraksi yang berbeda antar mesin. Perbaikannya adalah meratakan struktur di tahap transformasi agar tabelnya netral terhadap alat.

Ringkasan#

  • JSON membangun data dari object dan array yang boleh bersarang, sedangkan tabel analitik menuntut bentuk datar dengan kolom tetap.
  • Aturan perataan yang lazim mengubah object bersarang menjadi kolom bernama gabungan dan array of object menjadi baris dengan kunci induk yang diulang.
  • Perulangan murni memperlihatkan mekanisme perataan secara eksplisit, sedangkan json_normalize menerapkan aturan yang sama secara siap pakai.

Referensi#