Pourquoi écrivons-nous cet article ? Nous sommes Geonode et nous vendons des proxys à des personnes qui collectent des données ; nous constatons donc régulièrement que de nombreux ensembles de données extraites sont enregistrés sur disque dans un format inadapté. La mise en garde est simple : le choix du format n’a rien à voir avec les proxys et nous ne tirons aucun profit de votre décision à ce sujet. En revanche, cela a une incidence sur votre facture de stockage, votre temps de traitement et le temps que vous passez chaque semaine à déboguer pourquoi un champ contenant une virgule a fait échouer une importation en aval. Ce sont là des coûts réels, et vous pouvez les contrôler entièrement avant même d’écrire le premier enregistrement.
La différence fondamentale : l’un est une norme, l’autre une habitude
C’est ce qu’il faut comprendre en premier lieu, car tout le reste en découle.
JSON est normalisé. La RFC 8259 est un document relevant de la procédure de normalisation Internet. Il possède une grammaire formelle, des exigences obligatoires, et son existence a pour but explicite d’éliminer les « incohérences avec d’autres spécifications de JSON » et de corriger les « erreurs de spécification ». Si deux analyseurs JSON ne s’accordent pas, au moins l’un d’entre eux a tort et la spécification indique lequel.
Ce n’est pas le cas du CSV. La RFC 4180 est un document informatif, et elle le précise elle-même en termes on ne peut plus clairs :
Bien qu’il existe diverses spécifications et implémentations du format CSV… il n’existe aucune spécification formelle, ce qui permet une grande variété d’interprétations des fichiers CSV. Cette section documente le format qui semble être suivi par la plupart des implémentations.
L’expression « qui semble être suivi par la plupart des implémentations » revêt une grande importance dans cette phrase. La RFC 4180 est une description des pratiques courantes, et non une définition. Si deux analyseurs CSV ne s’accordent pas, les deux peuvent avoir raison.
C’est pourquoi les problèmes liés au CSV présentent ces caractéristiques. Il ne s’agit pas tant de bogues que de divergences légitimes concernant un format que personne n’a jamais entièrement défini — ce qui explique également pourquoi ils apparaissent aux interfaces d’intégration, plusieurs mois après la création du fichier, dans les outils d’un tiers.
Ce que le format CSV garantit réellement
La norme RFC 4180 définit les conventions courantes, et il est utile de les connaître car c'est dans les écarts par rapport à celles-ci que résident les problèmes.
Les enregistrements sont séparés par un CRLF. Le dernier enregistrement peut comporter ou non un saut de ligne à la fin. Il peut y avoir une ligne d'en-tête facultative. Les champs sont séparés par des virgules, chaque ligne doit comporter le même nombre de champs, et « les espaces sont considérés comme faisant partie d'un champ et ne doivent pas être ignorés ».
C'est au niveau des guillemets que les choses deviennent intéressantes :
Chaque champ peut être ou non encadré de guillemets doubles (cependant, certains programmes, tels que Microsoft Excel, n'utilisent pas du tout de guillemets doubles).
Et les champs « contenant des sauts de ligne (CRLF), des guillemets doubles et des virgules doivent être placés entre guillemets doubles », un guillemet double intégré étant échappé « en le faisant précéder d’un autre guillemet double ».
Notez les verbes modaux. « Peut ou non ». « Doit ». La RFC décrit des tendances. Et la parenthèse concernant Excel montre que le document reconnaît, en 2005, que l’outil CSV le plus utilisé au monde ne respecte pas cette convention.
Les conséquences pratiques, dans l’ordre où elles vous poseront problème :
Les délimiteurs varient selon les paramètres régionaux. Les pays utilisant une virgule comme séparateur décimal utilisent généralement un point-virgule comme délimiteur de champ. Un fichier exporté par un collègue en Allemagne risque de ne pas s’analyser correctement avec un lecteur utilisant des virgules, et aucun de vous deux n’a commis d’erreur.
L’encodage n’est pas déclaré. Rien dans un fichier CSV n’indique son encodage de caractères. UTF-8, Latin-1, Windows-1252 et UTF-16 produisent tous un fichier qui ressemble à du CSV mais s’affiche en caractères illisibles (« mojibake ») avec un analyseur inadapté. Les marqueurs d’ordre des octets apparaissent de manière incohérente et empêchent une analyse correcte des en-têtes.
Les fins de ligne varient. CRLF, LF et — dans les champs contenant des sauts de ligne intégrés — « either », à l’intérieur des guillemets.
Les types n’existent pas. Tout est du texte. 007 devient 7, 2026-09-02 devient une date dans un outil et une chaîne de caractères dans un autre, et un + en début de ligne disparaît. Le traitement d’un fichier CSV via un tableur entraîne de réelles pertes d’informations.
Et les fichiers CSV peuvent exécuter du code. Un champ commençant par =, +, - ou @ peut être interprété comme une formule par un tableur. Il s’agit d’une injection de formule, ce qui constitue une véritable vulnérabilité lorsque vous enregistrez des données fournies par l’utilisateur dans un fichier CSV que quelqu’un ouvrira dans Excel ; pour y remédier, il faut préfixer ces champs d’un guillemet simple ou les neutraliser d’une autre manière avant de les enregistrer. Si votre pipeline génère des fichiers CSV à partir de contenu extrait ou soumis par les utilisateurs, cela mérite d’être géré avec soin.
Ce que garantit JSON et ses limites
La spécification de JSON est plus stricte, et les garanties qui en découlent sont d'autant plus solides.
L'encodage est clairement défini. RFC 8259 §8.1 : « Le texte JSON échangé entre des systèmes ne faisant pas partie d'un écosystème fermé DOIT être encodé en UTF-8. » Elle stipule également que les implémentations « NE DOIVENT PAS ajouter de marque d’ordre des octets » au texte JSON échangé sur le réseau, tout en autorisant les analyseurs à l’ignorer. L’ensemble des problèmes liés à la devinette de l’encodage qui affligent le format CSV n’existe tout simplement pas ici.
Les types existent. Les chaînes de caractères, les nombres, les booléens, la valeur null, les objets et les tableaux sont distinguables dans la grammaire. "007" et 7 sont des valeurs différentes et le restent.
L’imbrication est native. Les données hiérarchiques ont une représentation évidente plutôt que de nécessiter une convention sur laquelle personne ne s’est mis d’accord.
Deux points sur lesquels JSON est moins absolu que ce que l’on croit généralement :
Les clés en double sont simplement déconseillées. La spécification indique : « Les noms au sein d’un objet DEVRAIENT être uniques » — DEVRAIENT, et non DOIVENT. Et elle est franche quant à la conséquence : lorsque les noms ne sont pas uniques, « le comportement du logiciel qui reçoit un tel objet est imprévisible. De nombreuses implémentations ne renvoient que la dernière paire nom/valeur. D’autres implémentations signalent une erreur ou échouent à l’analyse. »
La précision des nombres est une recommandation, pas une règle. La spécification autorise les implémentations à fixer des limites de plage et de précision, et observe qu’une bonne interopérabilité repose sur le fait de ne pas attendre plus que ce que fournit la norme IEEE 754 binary64. Elle nomme directement le cas d’échec : « Un nombre JSON tel que 1E400 ou 3.141592653589793238462643383279 peut indiquer des problèmes potentiels d’interopérabilité. »
En pratique, il s’agit d’un bug silencieux qui se glisse dans les applications. Les grands identifiants 64 bits perdent en précision lorsqu’ils sont analysés en nombres JavaScript ; aucune exception n’est levée, et deux enregistrements distincts peuvent prendre la même valeur. La solution standard consiste à sérialiser les grands entiers sous forme de chaînes de caractères — ce qu’il vaut mieux faire au moment de l’écriture des données plutôt que de s’en rendre compte en aval. Nous avons abordé l’aspect « analyseur » de ce problème dans notre guide sur JSON.parse.
Taille et vitesse
Le compromis est bien réel, et la tendance n'est pas toujours celle à laquelle on s'attend.
Le format CSV est plus léger pour les données tabulaires plates, généralement de manière significative, car les noms de champs n’apparaissent qu’une seule fois dans l’en-tête plutôt que dans chaque enregistrement. Un million de lignes comportant cinq champs stocke cinq noms de champs au format CSV et cinq millions au format JSON.
La compression réduit considérablement cet écart. Les clés répétées se compressent extrêmement bien. Après compression gzip, la perte de performance du JSON sur des enregistrements uniformes tombe souvent à un niveau modeste — voire, parfois, à zéro. Si vous stockez des données compressées, comme vous devriez le faire, l’argument de la taille en faveur du CSV est bien moins convaincant que ne le suggèrent les chiffres bruts.
Le CSV s’analyse plus rapidement dans les cas simples et plus lentement dans les cas corrects. Un analyseur naïf (split(',')) est très rapide, mais erroné. Un analyseur conforme, qui gère correctement les guillemets, les sauts de ligne intégrés et les guillemets échappés, se rapproche davantage du coût d’analyse de JSON. La plupart des comparaisons de vitesse entre CSV comparent en réalité, sans le dire, un analyseur incorrect à un analyseur correct.
Le véritable coût de JSON réside dans la mémoire, et non dans le processeur. Un seul document JSON volumineux doit généralement être conservé en mémoire pour être analysé. Un fichier CSV peut être traité ligne par ligne à partir d’un flux avec une consommation de mémoire constante. Pour un fichier de dix gigaoctets, cette différence n’est pas un simple détail de performance ; c’est la différence entre ce qui est possible et ce qui est impossible sur une machine donnée.
C’est exactement le problème que la section suivante résout.
Le juste milieu : JSON Lines
JSON Lines — également appelé NDJSON ou JSON délimité par des sauts de ligne — consiste en un document JSON par ligne, sans tableau englobant. C'est le format que la plupart des gens devraient utiliser, mais que relativement peu connaissent.
{"id": 1, "name": "Ada", "tags": ["engineer"]}
{"id": 2, "name": "Grace", "tags": ["engineer", "admiral"]}
Ce qu'il vous apporte :
Traitement en continu. Chaque ligne est analysée indépendamment, ce qui vous permet de traiter un fichier de cent gigaoctets en mémoire constante. Cela élimine le principal inconvénient pratique de JSON.
Écritures en ajout uniquement. Les nouveaux enregistrements sont ajoutés à la fin. Il n’y a pas de tableau englobant à fermer, ce qui signifie qu’il n’y a pas de réécriture du fichier ni de sortie corrompue si un processus s’arrête en cours d’écriture.
Récupération partielle. Un fichier tronqué permet toujours de récupérer toutes les lignes complètes. Un tableau JSON tronqué ne permet de récupérer absolument rien : il suffit d’une parenthèse manquante pour que l’ensemble du document devienne impossible à analyser. Pour tout ce qui est écrit par une tâche s’exécutant sur une longue durée, cela suffit à justifier à lui seul ce choix.
Parallélisme trivial. Division par ligne et traitement indépendant des fragments. Pas d’état inter-lignes.
Sémantique JSON complète. Types, imbrication et encodage sans ambiguïté : tout est conservé.
Les inconvénients sont minimes et transparents : un format légèrement plus volumineux que le CSV, impossible à ouvrir directement dans un tableur, et chaque enregistrement comporte ses propres clés. Pour les données extraites, les fichiers journaux, les flux d’événements et tout ce qui est ajouté de manière incrémentielle, c’est le choix par défaut idéal — et c’est ce que nous recommandons à quiconque écrit les résultats d’une collecte sur disque.
Au-delà des deux : Parquet et ses dérivés
Bon à savoir, car pour les charges de travail analytiques, la question « JSON ou CSV ? » est parfois complètement hors de propos.
Parquet est un format en colonnes et binaire. Il stocke chaque colonne de manière contiguë, ce qui signifie qu’une requête portant sur trois colonnes de quarante lignes ne lit que ces trois-là. Il intègre un schéma, offre une bien meilleure compression que le texte orienté lignes car les valeurs similaires sont regroupées, et préserve exactement les types de données.
Ses atouts : les requêtes analytiques sur de grands ensembles de données, le stockage à long terme de tout volume important, et tout pipeline alimentant un entrepôt de données. Les taux de compression par rapport au format CSV sont souvent plusieurs fois supérieurs, et les différences de performances des requêtes sont encore plus marquées.
Ses points faibles : il n’est pas lisible par l’homme, il ne permet pas d’ajouter des données à la fin comme le fait JSON Lines, et il nécessite une bibliothèque plutôt qu’un éditeur de texte. Pour le streaming, pour les échanges entre personnes et pour les petites quantités de données, les formats texte restent le choix approprié.
Une architecture courante et judicieuse : collecter les données au format JSON Lines, car il facilite l’ajout de données et tolère les pertes, puis les convertir par lots au format Parquet pour l’analyse et l’archivage. Chaque format est utilisé là où ses propriétés sont les plus utiles.
Choix en fonction de l'utilisation
| Utilisation | Format | Pourquoi |
|---|---|---|
| Réponse d'une API Web | JSON | Natif aux outils HTTP, aux types et à l'imbrication |
| Données extraites et enregistrées de manière incrémentielle | JSON Lines | Peut être ajouté à la fin, transmissible en flux continu, résiste à la troncature |
| Envoi de données à un collègue non technicien | CSV | S'ouvre dans Excel, ce qui correspond à l'exigence réelle |
| Configuration | Ni l'un ni l'autre — YAML ou TOML | Les commentaires sont importants |
| Grand ensemble de données analytiques | Parquet | Lecture en colonnes, compression, schéma |
| Importation en masse dans une base de données | CSV | Chargeurs natifs à chemin rapide dans la plupart des bases de données |
| Flux d’événements ou de journaux | JSON Lines | Un événement par ligne, ajout uniquement |
| Enregistrements imbriqués ou de forme variable | JSON ou JSON Lines | Le CSV ne peut pas les représenter sans inventer des conventions |
| Données contenant du texte fourni par l’utilisateur | JSON ou JSON Lines | Évite les risques liés aux guillemets, aux délimiteurs et à l’injection de formules |
Trois règles qui permettent de résoudre la plupart des cas sans avoir besoin du tableau.
Si les données sont plates, uniformes et destinées à une feuille de calcul ou à un chargeur en masse, utilisez le format CSV. Ce sont là les véritables atouts du CSV, et aucun autre format ne les offre avec autant de commodité. L’importation en masse dans une base de données, en particulier, constitue un réel avantage : la plupart des moteurs disposent d’un traitement accéléré pour le CSV, mais pas pour le JSON.
Si les données sont imbriquées, de structure variable ou contiennent du texte saisi par l’utilisateur, utilisez JSON ou JSON Lines. Aplatir des données imbriquées au format CSV nécessite d’inventer une convention, et toutes les conventions inventées à cette fin ont été source de bogues. Par ailleurs, le texte saisi par l’utilisateur contient des virgules, des guillemets et des sauts de ligne, ce que le format CSV gère justement de la manière la moins fiable.
Si vous enregistrez des enregistrements en continu, utilisez JSON Lines. Pas le format CSV, car celui-ci ne gère pas les types de données et vous risquez de les perdre. Pas non plus un tableau JSON, car il est impossible d’y ajouter des éléments en toute sécurité et un processus qui plante laisse un fichier impossible à analyser.
Questions fréquentes
Le format JSON est-il meilleur que le CSV ?
Selon l’usage, oui et non. Le JSON est une norme formelle qui définit des types, une imbrication et un encodage UTF-8 obligatoire. Le CSV est plus léger pour les données tabulaires plates, s’affiche naturellement sous forme de flux et s’ouvre dans des tableurs. L'argument le plus convaincant est que le format CSV ne dispose d'aucune spécification formelle — la RFC 4180 le précise explicitement —, ce qui le rend moins prévisible d'un outil à l'autre.
Pourquoi mon fichier CSV ne s'affiche-t-il pas correctement dans Excel ?
Généralement, cela est dû à l'encodage ou au délimiteur. Les fichiers CSV ne déclarent pas leur encodage de caractères ; Excel doit donc le deviner. De plus, les paramètres régionaux utilisant une virgule comme séparateur décimal s’attendent à un délimiteur point-virgule. Ces deux problèmes sont inhérents à un format qui n’a jamais spécifié ni l’un ni l’autre. L’exportation en UTF-8 avec un BOM aide souvent dans le cas spécifique d’Excel, au prix d’une confusion pour d’autres analyseurs syntaxiques.
Qu’est-ce que JSON Lines et quand dois-je l’utiliser ?
Un document JSON par ligne, sans tableau d’encapsulation. Utilisez-le chaque fois que vous écrivez des enregistrements de manière incrémentielle : données extraites, journaux, flux d’événements. Il s’écoule en mémoire constante, s’ajoute en toute sécurité, résiste à la troncature en conservant chaque ligne complète intacte, et préserve l’intégralité des types JSON et de l’imbrication.
Le format CSV est-il plus léger que le JSON ?
Non compressé et pour des données plates et uniformes, généralement de beaucoup, car les noms de champs n’apparaissent qu’une seule fois plutôt qu’à chaque enregistrement. Après compression, l’écart se réduit considérablement, car les clés répétées se compressent très bien. Si vous stockez des données compressées, l’argument de la taille en faveur du CSV est bien moins convaincant que ne le suggèrent les chiffres bruts.
Le format CSV peut-il gérer des données imbriquées ?
Pas de manière native. Toute imbrication nécessite une convention que vous devez définir vous-même : aplatissement avec des noms de colonnes séparés par des points, chaînes JSON à l’intérieur des cellules ou plusieurs fichiers liés. Toutes ces méthodes fonctionnent, mais elles impliquent que votre fichier CSV ne sera plus lisible par des outils génériques sans votre convention spécifique, ce qui va à l’encontre de la raison principale pour laquelle on utilise le format CSV.
Quel format est le plus rapide à analyser : JSON ou CSV ?
Le CSV, dans les cas simples, mais la comparaison est souvent inéquitable : un analyseur rapide (split(',')) n’est pas un analyseur CSV correct, et un analyseur gérant correctement les guillemets et les sauts de ligne intégrés se rapproche beaucoup plus du JSON en termes de coût. La différence la plus importante concerne la mémoire : le CSV s’écoule ligne par ligne, tandis qu’un document JSON doit généralement être chargé dans son intégralité, ce que résout JSON Lines.
Les clés en double sont-elles autorisées en JSON ?
La spécification indique que les noms « DEVRAIENT être uniques » plutôt que « DOIVENT » l’être ; elles sont donc techniquement autorisées. Elle prévient également que le comportement est imprévisible lorsqu’elles ne le sont pas : certains analyseurs conservent la dernière, d’autres renvoient une erreur, d’autres encore échouent complètement. Considérez les doublons comme un bug dans le programme ayant généré le document.
Quel format dois-je utiliser pour les données extraites ?
JSON Lines, dans la plupart des cas. Les enregistrements extraits sont souvent imbriqués et de structure variable, ce que le format CSV gère mal, et leur collecte est incrémentielle, ce que les tableaux JSON gèrent mal. Si les données sont véritablement « plates » et destinées à un tableur ou à un chargement en masse, le format CSV convient parfaitement — et si vous générez un fichier CSV à partir d’un texte extrait, neutralisez les champs commençant par =, +, - ou @ afin d’éviter l’injection de formules.
En conclusion
Ce qui facilite ce choix, ce n’est pas l’opposition entre « structuré » et « simple ». C’est le fait que l’un de ces formats repose sur une spécification, tandis que l’autre repose sur une description des pratiques courantes. La RFC 8259 définit ce que JSON doit faire ; la RFC 4180 décrit ce que les fichiers CSV semblent généralement faire, et l’exprime clairement dans ses propres termes.
Cette différence est à l’origine de pratiquement tous les problèmes liés au CSV : encodages non déclarés, délimiteurs dépendants des paramètres régionaux, utilisation incohérente des guillemets, types perdus sans avertissement lors du passage par un tableur, et champs transformés en formules. Aucun de ces problèmes n’est un bug dans un analyseur syntaxique quelconque. Il s’agit du résultat prévisible d’un format qui n’a jamais été entièrement défini.
Pour la plupart des personnes qui écrivent des données plutôt que de les lire, JSON Lines est la solution, mais il est sous-utilisé. Il conserve les types, l’imbrication et l’encodage bien établi de JSON tout en supprimant sa seule véritable faiblesse : il permet un traitement en continu, ajoute des données en toute sécurité et résiste à une écriture tronquée tout en conservant chaque enregistrement complet intact. Réservez le CSV aux deux tâches pour lesquelles il excelle véritablement : fournir un tableau plat à quelqu’un qui l’ouvrira dans un tableur, et charger en masse une base de données. Et si l’ensemble de données est volumineux et destiné à l’analyse, aucun de ces deux formats texte n’est la destination finale appropriée ; convertissez-le en un format en colonnes et laissez chaque format remplir la fonction pour laquelle il a été conçu.
