Lewati ke konten
Toova
Semua Alat

Cara Memformat JSON di JavaScript — 5 Metode

Toova

JSON ada di mana-mana: respons API, file konfigurasi, ekspor basis data, pipeline log. Tetapi output JSON mentah seringkali berupa blob yang ringkas — tanpa jeda baris, tanpa indentasi, key dalam urutan apa pun yang dikeluarkan oleh serializer. Itu membuat debugging menyakitkan dan kolaborasi lebih sulit dari yang seharusnya.

JavaScript memberi Anda beberapa cara untuk memformat JSON, dari JSON.stringify bawaan hingga library streaming untuk file yang terlalu besar untuk dimuat ke memori. Panduan ini menelusuri lima metode praktis, mencakup kasus paling umum dan edge case yang menangkap developer lengah.

Metode 1: JSON.stringify dengan Indentasi

Pendekatan paling sederhana sudah ada di dalam bahasa. JSON.stringify menerima tiga argumen: nilai yang akan diserialisasi, replacer (lebih lanjut tentang itu di Metode 2), dan parameter space yang mengontrol indentasi.

const data = {
  name: "Alice",
  role: "engineer",
  skills: ["JavaScript", "TypeScript", "Node.js"],
  active: true,
};

// Indent 2-spasi (default umum)
console.log(JSON.stringify(data, null, 2));

// Indent 4-spasi
console.log(JSON.stringify(data, null, 4));

// Indent tab
console.log(JSON.stringify(data, null, "\t"));

Dengan null, 2, outputnya terlihat seperti ini:

{
  "name": "Alice",
  "role": "engineer",
  "skills": [
    "JavaScript",
    "TypeScript",
    "Node.js"
  ],
  "active": true
}

Dua spasi adalah konvensi paling umum di proyek JavaScript — ia cocok dengan default di ESLint, Prettier, dan sebagian besar panduan gaya. Empat spasi umum di perkakas berdekatan-Python. Saat space dihilangkan atau diatur ke 0, outputnya adalah string satu baris yang ringkas — ideal untuk transmisi melalui jaringan.

Anda juga dapat memformat JSON seketika di peramban menggunakan alat JSON Formatter — tempel JSON mentah, dapatkan output yang pretty-print, dan salin hasilnya tanpa menulis kode apa pun.

Metode 2: Fungsi Replacer Kustom

Argumen kedua ke JSON.stringify — replacer — adalah fungsi atau array yang memfilter dan mentransformasi nilai sebelum serialisasi. Di sinilah Anda mendapat kontrol nyata atas apa yang berakhir di output.

Bentuk array adalah pendekatan paling sederhana untuk whitelisting key:

const user = {
  id: 42,
  name: "Bob",
  password: "s3cr3t",
  email: "bob@example.com",
  createdAt: new Date(),
};

// Replacer array: sertakan hanya key yang terdaftar
const safeJson = JSON.stringify(user, ["id", "name", "email"], 2);
console.log(safeJson);
// {
//   "id": 42,
//   "name": "Bob",
//   "email": "bob@example.com"
// }

Bentuk fungsi memberi Anda kontrol per-nilai. Kembalikan nilai untuk menyertakannya, kembalikan undefined untuk menghapusnya, atau kembalikan nilai yang ditransformasi:

function replacer(key, value) {
  // Hapus key yang dimulai dengan underscore (konvensi pribadi)
  if (key.startsWith("_")) return undefined;

  // Masking field sensitif
  if (key === "password" || key === "token") return "[REDACTED]";

  // Konversi objek Date ke string ISO secara eksplisit
  if (value instanceof Date) return value.toISOString();

  return value;
}

const payload = {
  id: 1,
  name: "Carol",
  password: "hunter2",
  _internalFlag: true,
  lastLogin: new Date("2026-05-01"),
};

console.log(JSON.stringify(payload, replacer, 2));
// {
//   "id": 1,
//   "name": "Carol",
//   "password": "[REDACTED]",
//   "lastLogin": "2026-05-01T00:00:00.000Z"
// }

Replacer berjalan secara rekursif pada setiap objek dan array bersarang. Pola ini berguna untuk pipeline logging di mana Anda ingin menghapus kredensial sebelum menulis ke disk atau mengirim ke layanan observabilitas.

Metode 3: Pretty-Print dengan Key Terurut

Objek JavaScript tidak menjamin urutan key (meskipun V8 dan sebagian besar mesin mempertahankan urutan penyisipan untuk key string). Saat Anda membutuhkan output deterministik — untuk diffing, caching, atau representasi kanonis — mengurutkan key secara alfabetis adalah langkah yang tepat.

function sortedStringify(value, indent = 2) {
  return JSON.stringify(value, sortReplacer, indent);
}

function sortReplacer(key, value) {
  if (value !== null && typeof value === "object" && !Array.isArray(value)) {
    return Object.keys(value)
      .sort()
      .reduce((sorted, k) => {
        sorted[k] = value[k];
        return sorted;
      }, {});
  }
  return value;
}

const config = {
  version: "1.0",
  author: "Dave",
  dependencies: { typescript: "^5.4", eslint: "^9.0", astro: "^5.0" },
  name: "my-project",
};

console.log(sortedStringify(config));
// {
//   "author": "Dave",
//   "dependencies": { "astro": "^5.0", "eslint": "^9.0", "typescript": "^5.4" },
//   "name": "my-project",
//   "version": "1.0"
// }

Key terurut berarti git diff hanya menampilkan baris yang benar-benar berubah, alih-alih penyusunan ulang sembarangan dari serializer yang berbeda. Ini sangat berguna untuk package.json dan file konfigurasi serupa yang dimasukkan ke kontrol versi.

Untuk mengonversi JSON ke format lain, alat JSON ke YAML dan alat JSON ke CSV juga menangani pengurutan key dalam outputnya.

Metode 4: Format dari String (Parse + Stringify)

JSON dunia nyata biasanya tiba sebagai string — dari respons fetch, pembacaan file, tempelan clipboard, atau kolom TEXT basis data. Anda perlu mem-parsing-nya terlebih dahulu, lalu memformat ulang. Bagian krusialnya adalah penanganan error yang tepat: JSON tidak valid akan melempar error, dan Anda ingin menangkapnya dengan anggun.

function formatJsonString(rawString, indent = 2) {
  try {
    const parsed = JSON.parse(rawString);
    return { ok: true, result: JSON.stringify(parsed, null, indent) };
  } catch (err) {
    return { ok: false, error: err.message };
  }
}

const raw = '{"name":"Eve","scores":[100,95,88],"active":true}';
const { ok, result, error } = formatJsonString(raw);

if (ok) {
  console.log(result);
  // {
  //   "name": "Eve",
  //   "scores": [100, 95, 88],
  //   "active": true
  // }
} else {
  console.error("Parsing gagal:", error);
}

// Input tidak valid
const bad = '{"name": "Eve", "broken":}';
const r2 = formatJsonString(bad);
// { ok: false, error: "Unexpected token '}'" }

Membungkus error parse dalam objek kembalian yang terstruktur membuat fungsi ini aman digunakan di komponen UI dan skrip build tanpa mengelilingi setiap situs panggilan dalam try/catch. Dokumentasi MDN untuk JSON.stringify mencakup spesifikasi parameter lengkap, dan RFC 8259 mendefinisikan seperti apa JSON yang valid di tingkat protokol.

Metode 5: Streaming untuk File Besar

Metode 1–4 semuanya memuat seluruh struktur JSON ke memori sebelum memformat. Untuk file dalam rentang ratusan megabita atau multi-gigabita, ini memblokir event loop Node.js dan mungkin merusak proses sepenuhnya.

Pendekatan streaming membaca file dalam potongan dan menulis output yang diformat secara bertahap. Untuk NDJSON (satu objek JSON per baris, umum di file log dan ekspor basis data), pendekatan berbasis readline bekerja tanpa dependensi tambahan:

import { createReadStream, createWriteStream } from "node:fs";
import { createInterface } from "node:readline";

async function formatNdjsonFile(inputPath, outputPath) {
  const rl = createInterface({
    input: createReadStream(inputPath),
    crlfDelay: Infinity,
  });

  const output = createWriteStream(outputPath);

  for await (const line of rl) {
    if (!line.trim()) continue;
    try {
      const obj = JSON.parse(line);
      output.write(JSON.stringify(obj, null, 2) + "\n---\n");
    } catch (e) {
      output.write("[Baris JSON tidak valid: " + e.message + "]\n---\n");
    }
  }

  output.end();
}

NDJSON adalah format streaming paling sederhana: setiap baris adalah objek JSON yang valid dan lengkap. Banyak alat ekspor mendukungnya tepat karena ia mudah di-stream. Jika Anda mengontrol format ekspor data besar, lebih utamakan NDJSON daripada array JSON raksasa tunggal.

Edge Case yang Harus Diwaspadai

Ini adalah skenario di mana pemformatan JSON standar gagal secara diam-diam atau melempar error tak terduga.

Referensi Sirkuler

JSON.stringify melempar TypeError jika objek mereferensikan dirinya sendiri secara langsung atau tidak langsung. Perbaiki dengan replacer yang melacak objek yang dikunjungi menggunakan WeakSet:

function safeStringify(obj, indent = 2) {
  const seen = new WeakSet();
  return JSON.stringify(obj, (key, value) => {
    if (typeof value === "object" && value !== null) {
      if (seen.has(value)) return "[Circular]";
      seen.add(value);
    }
    return value;
  }, indent);
}

const a = { name: "circular" };
a.self = a;
console.log(safeStringify(a));
// { "name": "circular", "self": "[Circular]" }

WeakSet menyimpan referensi tanpa mencegah pengumpulan sampah, yang menghindari kebocoran memori di proses yang berjalan lama.

Nilai BigInt

JSON.stringify melempar TypeError untuk nilai BigInt karena spesifikasi JSON tidak memiliki tipe integer 64-bit. Konversi ke string di replacer Anda:

const data = { id: 9007199254740993n, value: 42 };

JSON.stringify(data, (key, value) =>
  typeof value === "bigint" ? value.toString() : value
, 2);
// { "id": "9007199254740993", "value": 42 }

Nilai Map dan Set

Map diserialisasi sebagai objek kosong dan Set diserialisasi sebagai array kosong — bukan konten mereka. Konversi mereka secara eksplisit di replacer:

const data = {
  tags: new Set(["json", "javascript"]),
  meta: new Map([["source", "api"]]),
};

JSON.stringify(data, (key, value) => {
  if (value instanceof Set) return [...value];
  if (value instanceof Map) return Object.fromEntries(value);
  return value;
}, 2);
// { "tags": ["json", "javascript"], "meta": { "source": "api" } }

Nilai undefined

Properti objek dengan nilai undefined dihapus secara diam-diam. Slot array dengan undefined menjadi null. Gunakan replacer untuk mengonversi undefined ke null saat Anda perlu mempertahankan semua key:

const obj = { a: 1, b: undefined, c: null };
JSON.stringify(obj, null, 2);
// { "a": 1, "c": null }  — "b" dihapus diam-diam

// Perbaiki:
JSON.stringify(obj, (key, value) =>
  value === undefined ? null : value
, 2);
// { "a": 1, "b": null, "c": null }

Format JSON Seketika di Peramban

Jika Anda perlu memformat blob JSON sekarang tanpa menulis kode apa pun, Toova JSON Formatter menanganinya dalam satu klik — tempel JSON mentah, dapatkan output yang pretty-print dengan indentasi 2 atau 4 spasi, dan salin hasilnya. Tanpa daftar, tanpa unggahan file, semuanya berjalan secara lokal di peramban Anda.

Untuk konversi antar format, JSON ke YAML dan JSON ke CSV mengikuti pendekatan mengutamakan-privasi yang sama — data Anda tidak pernah meninggalkan perangkat Anda.

Kesimpulan

Untuk sebagian besar kasus penggunaan, JSON.stringify(obj, null, 2) adalah yang Anda butuhkan. Tambahkan fungsi replacer saat Anda memerlukan filtering, masking, atau key terurut. Bungkus JSON.parse dalam try/catch saat menangani input eksternal. Jangkau streaming hanya saat ukuran file membuat parsing sinkron tidak praktis. Dan jaga edge case — ref sirkuler, BigInt, Map/Set, undefined — di benak Anda saat bekerja dengan bentuk data yang tidak biasa.