JSON (JavaScript Object Notation) adalah format pertukaran data de facto untuk API modern, berkas konfigurasi, dan penyimpanan ringan. Dibandingkan CSV, JSON mampu merepresentasikan struktur bertingkat: array di dalam object, object di dalam array, dan seterusnya. PHP hadir dengan ekstensi JSON yang selalu aktif berisi dua fungsi utama: json_decode() untuk mengubah JSON menjadi data PHP, dan json_encode() untuk sebaliknya. Pada Chapter ini kita akan mempelajari kedua arah konversi tersebut beserta validasi dan penanganan galatnya, sehingga data yang kita proses selalu dapat dipertanggungjawabkan.
Mengubah JSON menjadi Data PHP #
Fungsi json_decode() mengubah string JSON menjadi nilai PHP. Parameter keduanya, $associative, menentukan wujud hasilnya: false (bawaan) menghasilkan object stdClass, sedangkan true menghasilkan array asosiatif:
<?php
$json = '{"nama": "Budi", "umur": 28, "hobi": ["membaca", "coding"]}';
$obj = json_decode($json);
$arr = json_decode($json, true);
echo $obj->nama . "\n";
echo $arr["hobi"][1] . "\n";
echo get_debug_type($obj) . "\n";
echo get_debug_type($arr) . "\n";Output yang Dihasilkan:
Budi
coding
stdClass
arrayMari kita telaah kode di atas:
- Baris 4:
json_decode($json)tanpa parameter$associativemenghasilkan objectstdClass, sehingga nilainya diakses dengan sintaks panah:$obj->nama. - Baris 5:
json_decode($json, true)menghasilkan array asosiatif, sehingga nilainya diakses dengan kurung siku:$arr["hobi"][1]. - Baris 6-7:
get_debug_type()mengonfirmasi wujud kedua hasil —stdClassdanarray— dari eksekusi yang sama.
Array asosiatif umumnya lebih nyaman dipakai di kode prosedural karena bisa dimanipulasi dengan seluruh fungsi array seperti array_map() dan array_filter(). Selain kedua parameter tersebut, json_decode() juga menerima parameter $depth (kedalaman struktur maksimum, bawaan 512) dan $flags — kedalaman lebih dari 512 lapis akan membuat dekode gagal, sesuatu yang nyaris tidak pernah terjadi pada data wajar.
Mengubah Data PHP menjadi JSON #
Arah sebaliknya ditangani json_encode(). Perhatikan perilaku bawaannya terhadap karakter non-ASCII dan tanda garis miring:
<?php
$profil = [
"nama" => "Siti Rahayu",
"catatan" => "Harga sudah termasuk pajak — 10%",
"website" => "https://example.com/siti",
];
echo json_encode($profil) . "\n";
echo json_encode($profil, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\n";Output yang Dihasilkan:
{"nama":"Siti Rahayu","catatan":"Harga sudah termasuk pajak \u2014 10%","website":"https:\/\/example.com\/siti"}
{"nama":"Siti Rahayu","catatan":"Harga sudah termasuk pajak — 10%","website":"https://example.com/siti"}Baris pertama hasil menunjukkan perilaku bawaan: karakter em dash diubah menjadi \u2014 dan garis miring menjadi \/. Hasil tersebut tetap JSON yang sah, tetapi lebih sulit dibaca manusia. Baris kedua menggunakan dua flag sekaligus dengan operator bitwise or (|): JSON_UNESCAPED_UNICODE mempertahankan karakter UTF-8 apa adanya dan JSON_UNESCAPED_SLASHES mempertahankan garis miring. Untuk data berbahasa Indonesia, kombinasi kedua flag ini sebaiknya menjadi kebiasaan default karena hasilnya lebih pendek dan lebih mudah dibaca.
Menyimpan JSON ke Berkas #
Pola umum pengolahan data adalah menyimpan hasil encode ke berkas, lalu membacanya kembali di eksekusi berikutnya. Flag JSON_PRETTY_PRINT membuat berkas mudah dibaca dan diperiksa manual:
<?php
$path = "/tmp/pengaturan.json";
$pengaturan = [
"tema" => "gelap",
"bahasa" => "id",
"notifikasi" => ["email" => true, "sms" => false],
];
$encode = json_encode($pengaturan, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
file_put_contents($path, $encode);
echo $encode . "\n";
$dibaca = json_decode(file_get_contents($path), true);
echo "Tema: " . $dibaca["tema"] . "\n";
echo ($dibaca["notifikasi"]["email"] ? "Notifikasi email aktif" : "Notifikasi email nonaktif") . "\n";Output yang Dihasilkan:
{
"tema": "gelap",
"bahasa": "id",
"notifikasi": {
"email": true,
"sms": false
}
}
Tema: gelap
Notifikasi email aktiffile_put_contents() menulis string JSON ke berkas, dan json_decode(file_get_contents($path), true) membacanya kembali menjadi array asosiatif. Tipe data ikut dipertahankan bolak-balik: boolean tetap true/false (bukan string "1"), integer tetap integer, dan null tetap null. Inilah keunggulan JSON dibanding CSV yang mengubah semua nilai menjadi string.
Memvalidasi JSON dengan json_validate #
Sebelum PHP 8.3, satu-satunya cara memeriksa keabsahan JSON adalah mencoba mendekodenya. Sejak PHP 8.3 tersedia json_validate() yang hanya memeriksa sintaks tanpa membangun struktur data, sehingga lebih murah untuk data besar:
<?php
$valid = '{"nama": "Budi", "umur": 28}';
$rusak = '{"nama": "Budi", "umur": 28,}';
echo (json_validate($valid) ? "valid" : "tidak valid") . "\n";
echo (json_validate($rusak) ? "valid" : "tidak valid") . "\n";Output yang Dihasilkan:
valid
tidak validVariabel $rusak memuat koma menggantung sebelum kurung kurawal penutup — kesalahan tipikal hasil penyambungan string manual. Fungsi json_validate() mengembalikan true hanya apabila seluruh dokumen lolos pemeriksaan sintaks. Fungsi ini cocok dipasang di gerbang pipeline: berkas JSON yang tidak lolos pemeriksaan langsung ditolak sebelum diproses lebih jauh.
Penanganan Galat Dekode #
json_decode() yang gagal hanya mengembalikan null — tanpa exception, tanpa peringatan. Dua gaya penanganan galat berikut menghasilkan informasi yang jauh lebih berguna:
<?php
$rusak = '{"nama": "Budi", "umur": 28,}';
$hasil = json_decode($rusak);
if ($hasil === null && json_last_error() !== JSON_ERROR_NONE) {
echo "Gaya manual : " . json_last_error_msg() . "\n";
}
try {
json_decode($rusak, true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
echo "Gaya exception: " . $e->getMessage() . "\n";
}Output yang Dihasilkan:
Gaya manual : Syntax error
Gaya exception: Syntax errorGaya pertama memanggil json_last_error() setelah dekode: apabila kode galatnya bukan JSON_ERROR_NONE, json_last_error_msg() memberikan pesan galat terakhir. Gaya kedua melewatkan flag JSON_THROW_ON_ERROR sehingga kegagalan dekode melempar JsonException yang bisa ditangkap try-catch — pendekatan yang lebih disarankan karena galat tidak mungkin terlupakan. Perlu dicatat pemeriksaan $hasil === null saja tidak cukup untuk gaya pertama, sebab JSON null yang sah juga didekode menjadi null; itulah alasan json_last_error() ikut diperiksa.
JSON vs serialize #
PHP juga punya mekanisme serialisasi native: serialize() dan unserialize(). Keduanya tidak saling menggantikan — pilihan bergantung pada kebutuhan:
| Aspek | JSON | serialize |
|---|---|---|
| Keterbacaan manusia | Ya, mudah dibaca | Format internal PHP |
| Portabilitas antar bahasa | Universal | Hanya PHP |
| Struktur bertingkat | Object dan array | Mendukung, termasuk object class |
| Memakai kembali object class | Tidak otomatis | Ya, dengan opsi allowed_classes |
JSON menang untuk pertukaran data antar sistem dan penyimpanan yang mungkin dibaca alat lain. serialize() unggul saat menyimpan nilai PHP secara internal — misalnya isi cache — karena mampu mempertahankan class dan referensi.
Ringkasan #
json_decode() mengubah JSON menjadi object stdClass atau array asosiatif melalui parameter $associative; json_encode() mengubah data PHP menjadi JSON dengan flag JSON_UNESCAPED_UNICODE, JSON_UNESCAPED_SLASHES, dan JSON_PRETTY_PRINT untuk hasil yang ramah dibaca. json_validate() (PHP 8.3+) memeriksa keabsahan sintaks secara murah, sementara flag JSON_THROW_ON_ERROR mengubah kegagalan dekode menjadi JsonException yang mudah ditangani. Format data ketiga yang masih banyak dipakai di sistem lama dan API berbasis SOAP adalah XML — pembacaannya memiliki pendekatan tersendiri yang akan kita pelajari pada Chapter berikutnya.