NDJSON

Qu’est-ce qu’un fichier NDJSON ?

Un objet JSON par ligne. Ce que font circuler les chaînes de journalisation et les exports de données.

Ce qu’est NDJSON

NDJSON est un format texte que n’importe quel éditeur ouvre. Il est utilisé pour l’échange entre programmes et la diffusion en continu.

L’extension est .ndjson et le nom complet Newline-Delimited JSON. L’un et l’autre comptent moins que ce que le fichier peut contenir, et c’est le sujet du reste de cette page.

D’où vient NDJSON

Il remonte à 2013.

L’âge est utile à connaître pour une raison pratique : plus un format est ancien, plus les programmes ont eu le temps de l’apprendre.

La spécification est publique

Elle est publiée intégralement : n’importe qui peut l’implémenter à partir du document plutôt qu’en l’observant, et c’est pourquoi ce format apparaît dans tant de programmes et pourquoi des fichiers écrits il y a vingt ans s’ouvrent encore. Une spécification publiée n’est pas pour autant libre de redevances : quand un format enveloppe un codec, les brevets sont une question à part, que la norme ne tranche pas.

Rien n’est jeté

NDJSON enregistre son contenu à l’identique. Le réenregistrer ne change rien : vous pouvez l’ouvrir, le modifier et le réenregistrer autant de fois que vous voulez sans accumuler de dégâts, et c’est ce qui en fait un format de travail plutôt qu’un format de livraison.

Ce qu’il peut porter d’autre

NDJSON peut contenir une disposition qui lui permet de commencer à jouer avant d’être arrivé en entier.

Cela compte surtout à la conversion : ce que la cible ne peut pas contenir est abandonné, en général sans avertissement.

Il n’y a nulle part où laisser une note

NDJSON n’a pas de syntaxe de commentaires. Tout ce qui explique doit vivre hors du fichier, ce qui est bon à savoir avant de le choisir pour quelque chose qu’un humain modifiera à la main.

Ce qui ouvre NDJSON

jq et pandas le lisent, comme la plupart des programmes du même genre.

Quand un fichier ne s’ouvre pas, le format est rarement en cause : le plus souvent, c’est le programme qui est plus ancien que lui. Convertir vers quelque chose de plus ancien est le contournement fiable, et c’est à cela que sert le reste de ce site.

L’ouvrir dans un navigateur

Aucun navigateur ne le lit.

C’est de loin la raison la plus fréquente de le convertir : non pas que le format soit mauvais, mais que l’endroit où vous voulez montrer le fichier ne sache pas le lire.

C’est un format de travail

NDJSON est fait pour être ouvert et modifié. Gardez le fichier dans ce format tant que le travail dure, et exportez depuis lui chaque fois qu’une version finie est nécessaire.

Un tableau JSON ne peut pas être lu avant d’être terminé

C’est le problème que ce format résout. Un document JSON n’est valide qu’une fois arrivé le crochet fermant, donc un analyseur qui reçoit un tableau de dix gigaoctets d’enregistrements doit lire les dix gigaoctets en mémoire avant de pouvoir rendre le premier. Pour un flux de logs qui ne se termine jamais, il ne peut jamais rien rendre du tout.

NDJSON supprime le tableau. Chaque ligne est un objet JSON complet et indépendant, terminé par un retour à la ligne et entouré de rien. Un lecteur prend une ligne, l’analyse, la traite et l’oublie — donc l’utilisation mémoire est la taille du plus grand enregistrement plutôt que la taille du fichier, et un processus peut commencer le travail sur le premier enregistrement immédiatement.

L’ajout est l’autre moitié de l’argument

Ajouter un enregistrement à un tableau JSON signifie réécrire le fichier  : le crochet fermant est à la fin, et quelque chose doit aller avant lui. Ajouter un enregistrement à un fichier NDJSON signifie écrire une ligne.

C’est ce qui en fait le format naturel pour tout ce qui s’accumule dans le temps — journaux d’application, flux d’événements, pistes d’audit, données extraites, télémétrie. C’est aussi ce qui le rend sûr en concurrence d’une manière qu’un tableau JSON ne l’est pas  : une écriture unique d’une ligne sous la taille d’écriture atomique du système ne s’entrelacera pas avec la ligne d’un autre rédacteur, donc plusieurs processus peuvent ajouter au même fichier sans le corrompre.

Les dégâts sont contenus à une ligne

Un tableau JSON tronqué par un crash ou un disque plein est invalide dans son entier — un crochet manquant et un analyseur rejette tout le fichier, y compris les 99 % qui étaient arrivés parfaitement.

Un fichier NDJSON tronqué en cours d’écriture perd sa dernière ligne et rien d’autre. Chaque ligne complète avant elle s’analyse encore, et un lecteur peut sauter la cassée et continuer. Pour des données collectées sur des semaines et stockées sur un matériel qui finira par tomber en panne, cette différence n’est pas théorique.

Où on le rencontre

Expédition de logs et observabilité  : l’API bulk d’Elasticsearch, Logstash, Fluentd, Vector et la plupart des bibliothèques de journalisation structurée le parlent. Exports de données depuis des API qui renvoient plus de lignes qu’il n’en tient dans une réponse. Jeux de données d’apprentissage automatique, où les données d’entraînement sont un exemple par ligne et le fichier est lu dans une boucle de streaming.

Aussi comme format de transfert pour des requêtes de longue durée, où un serveur écrit un objet JSON par ligne au fur et à mesure que des résultats deviennent disponibles et où le client les traite à mesure qu’ils arrivent plutôt que d’attendre la réponse complète.

Les règles qui le font fonctionner

Un objet par ligne, et aucun retour à la ligne à l’intérieur. Une chaîne JSON peut légalement contenir un retour à la ligne échappé et ne doit jamais en contenir un littéral — un objet joliment imprimé étalé sur plusieurs lignes casse complètement le format, et c’est de loin la manière la plus fréquente dont un fichier NDJSON est mal généré.

UTF-8, pas de BOM, et un retour à la ligne à la fin de la dernière ligne plutôt qu’un manquant ou une ligne vide. Les fins de ligne doivent être du type à un seul caractère  : un retour chariot Windows avant chaque saut de ligne est toléré par la plupart des lecteurs et rejeté par certains, ce qui est exactement le genre de panne intermittente que personne n’aime diagnostiquer.

NDJSON, JSON Lines et JSONL

Trois noms pour la même chose. NDJSON est la spécification avec un type de média  ; JSON Lines est une description distincte d’un format identique  ; JSONL est l’extension que les gens utilisent, particulièrement en apprentissage automatique.

Les différences entre les spécifications sont cosmétiques — une note sur les fins de ligne ici, une extension autorisée là — et aucun outil en pratique ne les distingue. Un fichier avec l’une ou l’autre extension peut être passé à tout ce qui attend l’autre.

Convertir depuis et vers

Vers JSON, quand un consommateur veut un document unique  : enveloppez les lignes dans des crochets et joignez-les par des virgules. Trivial, et ça réintroduit le problème de mémoire, qui est généralement la raison pour laquelle le fichier était en NDJSON à la base.

Vers CSV, quand les données sont réellement des enregistrements plats et que quelqu’un veut un tableur. La difficulté est que JSON imbrique et que CSV ne le fait pas, donc les objets imbriqués doivent être aplatis en noms de colonnes pointés et les tableaux doivent être abandonnés ou joints — une étape avec perte qui convient pour le reporting et qui est fausse pour une archive.

Et vers Parquet pour tout ce qui est analytique. Un format colonnaire, compressé, typé se lit bien plus rapidement pour les requêtes que les gens exécutent réellement sur des données d’événements, et c’est là qu’une grande archive NDJSON veut généralement aboutir.

Les données, au même endroit

Identifiants et origine du format NDJSON.
Extension.ndjson, .jsonl
Type de médiaapplication/x-ndjson
Première publication2013