Diffusion JSON - JSON streaming

Le streaming JSON comprend des protocoles de communication pour délimiter les objets JSON construits sur des protocoles orientés flux de niveau inférieur (tels que TCP ), qui garantissent que les objets JSON individuels sont reconnus, lorsque le serveur et les clients utilisent le même (par exemple, codé implicitement). Ceci est nécessaire car JSON est un protocole non concaténatif (la concaténation de deux objets JSON ne produit pas un objet JSON valide).

introduction

JSON est un format populaire pour l'échange de données d'objets entre les systèmes. Il est souvent nécessaire d'envoyer un flux d'objets via une seule connexion, comme un téléscripteur ou des enregistrements de journal d'application . Dans ces cas, il est nécessaire d'identifier où se termine un objet encodé JSON et où commence le suivant. Techniquement, c'est ce qu'on appelle le cadrage .

Il existe quatre façons courantes d'y parvenir :

  • Envoyez les objets JSON formatés sans retour à la ligne et utilisez un retour à la ligne comme délimiteur.
  • Envoyez les objets JSON concaténés avec un caractère de contrôle de séparateur d'enregistrements comme délimiteur.
  • Envoyez les objets JSON concaténés sans délimiteurs et utilisez un analyseur de streaming pour les extraire.
  • Envoyez les objets JSON préfixés par leur longueur et utilisez un analyseur de streaming pour les extraire.

JSON délimité par des lignes

Les trois termes pour les formats équivalents de streaming JSON sont :

  • JSON délimité par des lignes (LDJSON),
  • Newline -delimited JSON (NDJSON), et
  • Lignes JSON (JSONL)

Le streaming utilise le fait que le format JSON n'autorise pas les caractères de retour et de nouvelle ligne dans les valeurs primitives (dans les chaînes, ceux-ci doivent être échappés en tant que \ret \n, respectivement) et que la plupart des formateurs JSON n'incluent par défaut aucun espace, y compris les retours et les nouvelles lignes. Ces fonctionnalités permettent d'utiliser le caractère de nouvelle ligne ou la séquence de caractères de retour et de nouvelle ligne comme délimiteur.

Ce format est spécifié sur ndjson.org et documenté sur le site Web JSON Lines .

Cet exemple montre deux objets JSON (les caractères de nouvelle ligne implicites à la fin de chaque ligne ne sont pas affichés) :

{"some":"thing\n"}
{"may":{"include":"nested","objects":["and","arrays"]}}

L'utilisation d'un saut de ligne comme délimiteur permet à ce format de très bien fonctionner avec les outils Unix traditionnels orientés ligne .

Un fichier journal, par exemple, pourrait ressembler à :

{"ts":"2020-06-18T10:44:12","started":{"pid":45678}}
{"ts":"2020-06-18T10:44:13","logged_in":{"username":"foo"},"connection":{"addr":"1.2.3.4","port":5678}}
{"ts":"2020-06-18T10:44:15","registered":{"username":"bar","email":"bar@example.com"},"connection":{"addr":"2.3.4.5","port":6789}}
{"ts":"2020-06-18T10:44:16","logged_out":{"username":"foo"},"connection":{"addr":"1.2.3.4","port":5678}}

qui est très facile à trier par date, grep pour les noms d'utilisateur, les actions, les adresses IP, etc.

JSON délimité par des séparateurs d'enregistrement

Le streaming JSON délimité par des séparateurs d'enregistrements permet de délimiter les séquences de texte JSON sans que le formateur JSON exclue les espaces. Étant donné que les séquences de texte JSON ne peuvent pas contenir de caractères de contrôle, un caractère de séparation d'enregistrement peut être utilisé pour délimiter les séquences. De plus, il est suggéré que chaque séquence de texte JSON soit suivie d'un caractère de saut de ligne pour permettre une gestion appropriée des objets JSON de niveau supérieur qui ne sont pas auto-délimitants (nombres, vrai, faux et nul).

Ce format est également connu sous le nom de séquences de texte JSON ou de type MIME application/json-seq et est formellement décrit dans IETF RFC 7464.

L'exemple ci-dessous montre deux objets JSON avec ␞ représentant le caractère de contrôle du séparateur d'enregistrement et ␊ représentant le caractère de saut de ligne :

{"some":"thing\n"}
{
  "may": {
    "include": "nested",
    "objects": [
      "and",
      "arrays"
    ]
  }
}

JSON concaténé

Le streaming JSON concaténé permet à l'expéditeur d'écrire simplement chaque objet JSON dans le flux sans délimiteurs. Il repose sur le récepteur utilisant un analyseur qui peut reconnaître et émettre chaque objet JSON lors de l' analyse du caractère de fin. JSON concaténé n'est pas un nouveau format, c'est simplement un nom pour diffuser plusieurs objets JSON sans aucun délimiteur.

L'avantage de ce format est qu'il peut gérer des objets JSON qui ont été formatés avec des caractères de nouvelle ligne intégrés, par exemple, joliment imprimés pour une lisibilité humaine. Par exemple, ces deux entrées sont toutes les deux valides et produisent la même sortie :

{"some":"thing\n"}{"may":{"include":"nested","objects":["and","arrays"]}}
{
  "some": "thing\n"
}
{
  "may": {
    "include": "nested",
    "objects": [
      "and",
      "arrays"
    ]
  }
}

Les implémentations qui reposent sur une entrée basée sur une ligne peuvent nécessiter un caractère de nouvelle ligne après chaque objet JSON afin que l'objet soit émis par l'analyseur en temps opportun. (Sinon, la ligne peut rester dans le tampon d'entrée sans être transmise à l'analyseur.) Cela est rarement reconnu comme un problème car il est très courant de terminer les objets JSON avec un caractère de nouvelle ligne.

JSON avec préfixe de longueur

Le streaming JSON avec préfixe de longueur ou encadré permet à l'expéditeur d'indiquer explicitement la longueur de chaque message. Il repose sur le récepteur utilisant un analyseur qui peut reconnaître chaque longueur n , puis lire les n octets suivants à analyser en tant que JSON.

L'avantage de ce format est qu'il peut accélérer l'analyse du fait que la longueur exacte de chaque message est explicitement indiquée, plutôt que de forcer l'analyseur à rechercher des délimiteurs. JSON avec préfixe de longueur est également bien adapté aux applications TCP, où un seul "message" peut être divisé en morceaux arbitraires, car la longueur préfixée indique à l'analyseur exactement combien d'octets il doit attendre avant d'essayer d'analyser une chaîne JSON.

Cet exemple montre deux objets JSON avec préfixe de longueur (chaque longueur étant la longueur en octets de la chaîne JSON suivante) :

18{"some":"thing\n"}55{"may":{"include":"nested","objects":["and","arrays"]}}

Comparaison

JSON délimité par des lignes fonctionne très bien avec les outils traditionnels orientés ligne .

Le JSON concaténé fonctionne avec du JSON joliment imprimé, mais son analyse nécessite plus d'efforts et de complexité. Cela ne fonctionne pas bien avec les outils traditionnels orientés ligne. Le streaming JSON concaténé est un sur-ensemble de streaming JSON délimité par des lignes.

Le JSON avec préfixe de longueur fonctionne avec du JSON joliment imprimé. Il ne fonctionne pas bien avec les outils traditionnels orientés ligne, mais peut offrir des avantages en termes de performances par rapport au streaming délimité par des lignes ou concaténé. Il peut également être plus simple à analyser.

Compatibilité

Le JSON délimité par des lignes peut être lu par un analyseur qui peut gérer le JSON concaténé. Le JSON concaténé qui contient des nouvelles lignes dans un objet JSON ne peut pas être lu par un analyseur JSON délimité par des lignes.

Les termes « JSON délimité par une ligne » et « JSON délimité par une nouvelle ligne » sont souvent utilisés sans préciser si les nouvelles lignes intégrées sont prises en charge.

Auparavant, la spécification NDJ ("JSON délimité par une nouvelle ligne") autorisait l'intégration de commentaires si les deux premiers caractères d'une ligne donnée étaient "//". Cela ne pourrait pas être utilisé avec les analyseurs syntaxiques JSON standard si des commentaires étaient inclus. La version actuelle de la spécification ("NDJSON - Newline delimited JSON") n'inclut plus de commentaires.

Le JSON concaténé peut être converti en JSON délimité par des lignes par un utilitaire JSON approprié tel que jq. Par example

jq --compact-output . < concatenated.json > lines.json

Applications et outils

JSON délimité par des lignes

JSON délimité par des séparateurs d'enregistrement

  • jq peut à la fois créer et lire des textes JSON délimités par des séparateurs d'enregistrement.

JSON concaténé

  • concatjson module d'analyseur/sérialiseur de streaming JSON concaténé pour Node.js
  • Jackson_(API) peut lire et écrire du contenu JSON concaténé.
  • processeur JSON de ligne de commande flexible et léger jq
  • Analyseur JSON en streaming de Noggit Solr pour Java
  • Yajl – Encore une autre bibliothèque JSON. YAJL est un petit analyseur JSON basé sur les événements (de style SAX) écrit en ANSI C et un petit générateur JSON de validation.
  • ArduinoJson est une bibliothèque C++ qui prend en charge JSON concaténé.
  • GSON JsonStreamParser.java peut lire le JSON concaténé.

JSON avec préfixe de longueur

  • missive Bibliothèque rapide et légère pour l'encodage et le décodage des messages JSON avec préfixe de longueur sur les flux
  • Messagerie native WebExtensions Messagerie native

Les références

  1. ^ Ryan, Film Grain. "Comment nous avons construit Filmgrain, partie 2 de 2" . filmgrainapp.com . Récupéré le 4 juillet 2013 .
  2. ^ "Lignes JSON" .
  3. ^ "RFC 7464" .
  4. ^ "Nouvelle ligne JSON délimité" .
  5. ^ "NDJSON - JSON délimité par une nouvelle ligne" . 2 juin 2021.
  6. ^ "Consignation centralisée avec Monolog, Logstash et Elasticsearch" .
  7. ^ "NDJSON - JSON délimité par une nouvelle ligne, une norme pour délimiter JSON dans les protocoles de flux" .