Comment formater du JSON en JavaScript — 5 méthodes
Le JSON est omniprésent : réponses d'API, fichiers de configuration, exports de bases de données, pipelines de logs. Mais la sortie JSON brute est souvent un blob compact — sans saut de ligne, sans indentation, les clés dans l'ordre où le sérialiseur les produit. Cela rend le débogage douloureux et la collaboration plus difficile qu'elle ne devrait l'être.
JavaScript vous offre plusieurs façons de formater du JSON, du JSON.stringify natif aux bibliothèques en streaming pour les fichiers trop volumineux pour être chargés en mémoire. Ce guide présente cinq méthodes pratiques, couvrant les cas les plus courants et les cas particuliers qui surprennent les développeurs.
Méthode 1 : JSON.stringify avec indentation
L'approche la plus simple est déjà intégrée au langage. JSON.stringify accepte trois arguments : la valeur à sérialiser, un replacer (voir Méthode 2), et un paramètre space qui contrôle l'indentation.
const data = {
name: "Alice",
role: "ingénieure",
skills: ["JavaScript", "TypeScript", "Node.js"],
active: true,
};
// Indentation 2 espaces (défaut courant)
console.log(JSON.stringify(data, null, 2));
// Indentation 4 espaces
console.log(JSON.stringify(data, null, 4));
// Indentation tabulation
console.log(JSON.stringify(data, null, " "));
Avec null, 2, la sortie ressemble à ceci :
{
"name": "Alice",
"role": "ingénieure",
"skills": [
"JavaScript",
"TypeScript",
"Node.js"
],
"active": true
}
Deux espaces est la convention la plus répandue dans les projets JavaScript — c'est le défaut dans ESLint, Prettier et la plupart des guides de style. Quatre espaces est courant dans les outils de l'écosystème Python. Lorsque space est omis ou défini à 0, la sortie est une chaîne compacte sur une seule ligne — idéale pour la transmission sur le réseau.
Vous pouvez également formater du JSON instantanément dans le navigateur avec l'outil Formateur JSON — collez du JSON brut, obtenez une sortie formatée et copiez le résultat sans écrire de code.
Méthode 2 : Fonction de remplacement personnalisée
Le deuxième argument de JSON.stringify — le replacer — est une fonction ou un tableau qui filtre et transforme les valeurs avant la sérialisation. C'est là que vous obtenez un vrai contrôle sur ce qui se retrouve dans la sortie.
La forme tableau est l'approche la plus simple pour la liste blanche de clés :
const user = {
id: 42,
name: "Bob",
password: "s3cr3t",
email: "bob@example.com",
createdAt: new Date(),
};
// Replacer tableau : inclure uniquement les clés listées
const safeJson = JSON.stringify(user, ["id", "name", "email"], 2);
console.log(safeJson);
// {
// "id": 42,
// "name": "Bob",
// "email": "bob@example.com"
// }
La forme fonction vous donne un contrôle par valeur. Retournez la valeur pour l'inclure, retournez undefined pour la supprimer, ou retournez une valeur transformée :
function replacer(key, value) {
// Supprimer les clés commençant par underscore (convention privée)
if (key.startsWith("_")) return undefined;
// Masquer les champs sensibles
if (key === "password" || key === "token") return "[REDACTED]";
// Convertir les objets Date en chaînes ISO explicitement
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"
// } Le replacer s'exécute récursivement sur chaque objet et tableau imbriqué. Ce schéma est utile pour les pipelines de logs où vous souhaitez retirer les identifiants avant d'écrire sur le disque ou d'envoyer vers un service d'observabilité.
Méthode 3 : Affichage formaté avec clés triées
Les objets JavaScript ne garantissent pas l'ordre des clés (bien que V8 et la plupart des moteurs préservent l'ordre d'insertion pour les clés chaînes). Lorsque vous avez besoin d'une sortie déterministe — pour le diff, la mise en cache ou les représentations canoniques — trier les clés alphabétiquement est la bonne approche.
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"
// }
Les clés triées signifient que les diffs git affichent uniquement les lignes qui ont réellement changé, plutôt que des réordonnements arbitraires provenant de différents sérialiseurs. C'est particulièrement utile pour les fichiers package.json et les fichiers de configuration similaires versionnés dans le dépôt.
Pour convertir du JSON vers d'autres formats, les outils JSON vers YAML et JSON vers CSV gèrent également l'ordre des clés dans leur sortie.
Méthode 4 : Formater depuis une chaîne (Parse + Stringify)
Dans la pratique, le JSON arrive généralement sous forme de chaîne — depuis une réponse fetch, un fichier lu, un collage depuis le presse-papier ou une colonne TEXT en base de données. Vous devez d'abord le parser, puis le reformater. L'élément essentiel est une gestion d'erreur appropriée : un JSON invalide lève une exception, et vous voulez la capturer gracieusement.
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("Échec du parsing :", error);
}
// Entrée invalide
const bad = '{"name": "Eve", "broken":}';
const r2 = formatJsonString(bad);
// { ok: false, error: "Unexpected token '}'" } Encapsuler les erreurs de parsing dans un objet de retour structuré rend cette fonction sûre à utiliser dans des composants UI et des scripts de build sans entourer chaque site d'appel d'un try/catch. La documentation MDN de JSON.stringify couvre la spécification complète des paramètres, et la RFC 8259 définit à quoi ressemble un JSON valide au niveau protocolaire.
Méthode 5 : Streaming pour les fichiers volumineux
Les méthodes 1 à 4 chargent toutes la structure JSON entière en mémoire avant de la formater. Pour les fichiers de plusieurs centaines de mégaoctets ou de plusieurs gigaoctets, cette approche bloque la boucle d'événements Node.js et peut faire planter le processus.
L'approche en streaming lit le fichier par morceaux et écrit la sortie formatée de façon incrémentielle. Pour le NDJSON (un objet JSON par ligne, courant dans les fichiers de logs et les exports de bases de données), une approche basée sur readline fonctionne sans dépendances supplémentaires :
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) + "
---
");
} catch (e) {
output.write("[Ligne JSON invalide : " + e.message + "]
---
");
}
}
output.end();
} NDJSON est le format de streaming le plus simple : chaque ligne est un objet JSON valide et complet. De nombreux outils d'export le prennent en charge précisément parce qu'il est trivialement streamable. Si vous contrôlez le format des exports de données volumineuses, préférez NDJSON à un seul grand tableau JSON.
Cas particuliers à surveiller
Ce sont les scénarios où le formatage JSON standard échoue silencieusement ou lève une exception de manière inattendue.
Références circulaires
JSON.stringify lève une TypeError si un objet se référence lui-même directement ou indirectement. Corrigez cela avec un replacer qui suit les objets visités en utilisant un 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]" }
Le WeakSet conserve les références sans empêcher le ramasse-miettes, ce qui évite les fuites mémoire dans les processus de longue durée.
Valeurs BigInt
JSON.stringify lève une TypeError pour les valeurs BigInt car la spécification JSON n'a pas de type entier 64 bits. Convertissez-les en chaîne dans votre replacer :
const data = { id: 9007199254740993n, value: 42 };
JSON.stringify(data, (key, value) =>
typeof value === "bigint" ? value.toString() : value
, 2);
// { "id": "9007199254740993", "value": 42 } Valeurs Map et Set
Map sérialise comme un objet vide et Set sérialise comme un tableau vide — pas leur contenu. Convertissez-les explicitement dans un 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" } } Valeurs undefined
Les propriétés d'objet avec des valeurs undefined sont silencieusement supprimées. Les éléments de tableau avec undefined deviennent null. Utilisez un replacer pour convertir undefined en null lorsque vous devez conserver toutes les clés :
const obj = { a: 1, b: undefined, c: null };
JSON.stringify(obj, null, 2);
// { "a": 1, "c": null } — "b" est silencieusement supprimé
// Correction :
JSON.stringify(obj, (key, value) =>
value === undefined ? null : value
, 2);
// { "a": 1, "b": null, "c": null } Formater du JSON instantanément dans le navigateur
Si vous devez formater un bloc JSON maintenant sans écrire de code, le Formateur JSON Toova le fait en un clic — collez du JSON brut, obtenez une sortie formatée avec une indentation de 2 ou 4 espaces, et copiez le résultat. Sans inscription, sans envoi de fichier, tout s'exécute localement dans votre navigateur.
Pour les conversions entre formats, JSON vers YAML et JSON vers CSV suivent la même approche axée sur la confidentialité — vos données ne quittent jamais votre appareil.
Conclusion
Pour la plupart des cas d'usage, JSON.stringify(obj, null, 2) est tout ce dont vous avez besoin. Ajoutez une fonction de remplacement lorsque vous avez besoin de filtrage, de masquage ou de clés triées. Encapsulez JSON.parse dans un try/catch lors du traitement d'entrées externes. Recourez au streaming uniquement lorsque la taille du fichier rend le parsing synchrone impraticable. Et gardez en mémoire les cas particuliers — refs circulaires, BigInt, Map/Set, undefined — lorsque vous travaillez avec des structures de données inhabituelles.