Formater JSON semble la chose la plus simple qu'un outil puisse faire :
ajouter des espaces et des sauts de ligne pour qu'un humain puisse le
lire. La plupart des formateurs font exactement cela en appelant
JSON.parse puis JSON.stringify avec un argument d'indentation. Ce
voyage aller-retour fonctionne pour le JSON que vous écrivez à la main et
se rompt silencieusement pour le JSON que vous obtenez d'ailleurs.
Les deux bugs causés par le voyage aller-retour
JSON.parse transforme chaque nombre en un double JavaScript. Un double
ne peut pas contenir chaque entier exactement après
Number.MAX_SAFE_INTEGER, qui est 9007199254740991. Un ID snowflake, une
clé primaire de base de données, ou un horodatage en nanosecondes peut
facilement dépasser ce seuil, et une fois qu'il le fait, la re-sérialisation
de la valeur analysée modifie les chiffres. 12345678901234567890 revient
sous la forme 12345678901234567000. Personne ne le remarque tant que
l'n'est pas erroné quelque part en aval.
Ce même voyage retour réordonne également les clés d'objet qui
ressemblent à des nombres, car JSON.stringify parcourt les clés
énumérables propres d'un objet JavaScript dans un ordre spécifique : les
clés de type entier d'abord, en ordre ascendant, puis tout le reste en
ordre d'insertion. Un document écrit comme {"2": "b", "1": "a"} revient
sous la forme {"1": "a", "2": "b"}, ce qui est un document différent
même si chaque valeur a survécu.
Ce que le formateur JSON fait à la place
Cet outil n'appelle jamais JSON.parse. Il tokenise votre document, valide
le flux de tokens par rapport à RFC 8259, et réimprime à partir de ces
tokens. Un nombre est copié comme les caractères exacts que vous avez écrits,
pas re-encodé via un double. Une clé reste où vous l'avez placée. En collant
{"2":"second","1":"first","id":12345678901234567890,"note":"line1\nline2"}
et en appuyant Formater, on obtient :
{
"2": "second",
"1": "first",
"id": 12345678901234567890,
"note": "line1\nline2"
}
"2" reste avant "1", et le id à vingt chiffres revient exactement
comme écrit. Seul l'espace a changé.
Lire une erreur
Si le document n'est pas du JSON valide, l'outil marque la ligne problématique dans la gouttière et nomme l'erreur réelle au lieu de citer le token sur lequel il s'est bloqué. Une virgule de fin avant une accolade fermante est signalée comme une virgule de fin, à la ligne où se trouve la virgule, pas à la fin du fichier où un analyseur simple abandonne.
Formater vs Minifier
Les deux boutons effectuent la même réimpression à partir des tokens ; seul l'espace diffère. Formater ajoute des sauts de ligne et la largeur d'indentation que vous avez choisie (2 espaces, 4 espaces, ou une tabulation). Minifier supprime chaque espace, tabulation et saut de ligne que JSON ne nécessite pas. Aucun ne modifie une valeur, il est donc sûr d'appuyer sur l'un ou l'autre autant de fois que vous le souhaitez, ou de basculer entre eux sans recoller.
Essayez-le sur un document avec un ID long ou un fichier de configuration
avec des clés numériques, et comparez le résultat avec un formateur qui
passe par JSON.parse. La différence apparaît immédiatement.