Sélectionnez votre langue

Anatomie d'un message JSON

Lire un message

Anatomie d'un message JSON

Un message Telebib2 en JSON tient en trois niveaux emboîtés : une enveloppe qui dit qui parle à qui, un ou plusieurs datablocks qui délimitent chacun une unité d'échange et à l'intérieur de chaque datablock le contenu métier : le message proprement dit. Rien de neuf sous le soleil : c'est le découpage qu'EDIFACT opère depuis toujours avec ses segments d'en-tête. Seule la syntaxe change.

Trois niveaux emboîtés. L'enveloppe, décrite par messageEnvelope.202701.json, porte quatre propriétés obligatoires : syntaxVersionNumber, senderIdentificationDetail, recipientIdentificationDetail et dataBlocks. Chaque datablock porte cinq propriétés obligatoires : exchangeUnitType, exchangeUnitActionCoded, exchangeUnitTypeVersionNumber, exchangeUnitIssuingFormat et content. Le contenu métier commence par la carte d'identité du message : le code du MIG, une chaîne, et sa version, un entier.
Fig. 01 - Les trois niveaux d'un message et leurs propriétés obligatoires

L'enveloppe : qui parle à qui

L'enveloppe est décrite par messageEnvelope.202701.json. Elle ne contient aucune donnée métier : son rôle est de transporter. Quatre propriétés y sont obligatoires.

  • syntaxVersionNumber - vaut toujours 1. C'est la version de la syntaxe Telebib2 JSON, pas celle de vos messages.
  • senderIdentificationDetail et recipientIdentificationDetail - l'adresse de domaine de chaque partie (35 caractères), éventuellement complétée d'une adresse utilisateur et d'un type codé.
  • dataBlocks - un tableau, avec au minimum un élément.

Deux propriétés facultatives méritent d'être connues. groupType qualifie le lot : elle devient nécessaire quand l'enveloppe mélange des types de datablocks différents, ou quand votre correspondant l'exige pour son routage. Et metadata, qui est le seul endroit de tout le message où vous pouvez déposer ce que vous voulez - un identifiant de corrélation, un horodatage de votre bus applicatif. Le reste du message est strictement fermé.

{
  "syntaxVersionNumber": 1,
  "senderIdentificationDetail": {
    "senderDomainAddress": "insurerA.telebib2.be",
    "senderTypeCoded": "sendingCompany"
  },
  "recipientIdentificationDetail": {
    "recipientDomainAddress": "insurerB.telebib2.be",
    "recipientTypeCoded": "receivingCompany"
  },
  "dataBlocks": []
}

Les datablocks : une unité d'échange 

Une enveloppe peut porter plusieurs datablocks : c'est ainsi qu'on envoie un lot (au même destinataire). Chaque datablock est autonome : son type, son action, sa référence, son contenu. Cinq propriétés y sont obligatoires : exchangeUnitType, exchangeUnitActionCoded, exchangeUnitTypeVersionNumber, exchangeUnitIssuingFormat et content.

Les deux premières situent le message : sa famille (contrat, sinistre, échange financier…) et l'action qu'il porte au sein de cette famille. exchangeUnitIssuingFormat vaut invariablement "json" . C'est ce qui distingue un message de la norme JSON d'un message  EDIFACT.

Restent les références libres, senderExchangeUnitIdentifier et recipientExchangeUnitIdentifier (17 caractères). Elles ne sont pas obligatoires, mais ce sont elles que vous retrouverez dans l'accusé de réception : les renseigner vous évitera de rapprocher des messages à l'aveugle.

{
  "exchangeUnitType": "contract_ExchangeUnit",
  "exchangeUnitActionCoded":
      "contractClaimsCertificateContractPart",
  "exchangeUnitTypeVersionNumber": "1",
  "exchangeUnitIssuingFormat": "json",
  "senderExchangeUnitIdentifier": "M0151-2026-001",
  "exchangeUnitIssueDateTime": "2026-08-31T09:15:00Z",
  "content": {}
}

Le contenu : le message métier

Tout ce qui relève de l'assurance vit dans content. Et les deux premières propriétés de cet objet forment la carte d'identité du message : exchangeUnitBusinessContentDescription nomme le MIG, exchangeUnitBusinessContentDescriptionVersion donne sa version.

Ces deux propriétés sont la transposition directe des éléments de données X943 et X944 d'EDIFACT. Notez le type : le code est une chaîne, la version est un entier. C'est une source d'erreur classique en début d'implémentation.

"content": {
  "exchangeUnitBusinessContentDescription": "M0151",
  "exchangeUnitBusinessContentDescriptionVersion": 3,
  "domain": "motor",
  "mainRenewalDateInMonthDay": "06-30"
}

Comment le validateur descend la cascade

Les schémas s'appellent les uns les autres. Vous ne validez jamais un MIG directement : vous validez l'enveloppe et la chaîne se déroule toute seule.

On valide messageEnvelope.202701.json, qui appelle messageDataBlock.202701.json par dataBlocks, qui appelle schemaRouter.json par content. Le routeur n'accepte que les couples X943 et X944 connus par un anyOf, puis aiguille vers le schéma du MIG par une série de if/then. Le schéma du MIG appelle enfin les composants partagés.
Fig. 02 - La cascade, de l'enveloppe au schéma métier

La pièce intéressante est schemaRouter.json, qui fait deux choses distinctes. D'abord un anyOf qui n'accepte que les couples X943+X944 connus : un message annonçant un MIG inexistant, ou une version retirée du service, est rejeté immédiatement plutôt que validé « par défaut ». Ensuite une série de if/then qui aiguille le contenu vers le bon fichier de schéma.

Le routeur est aussi la seule pièce du registre qui change sans changer de nom : il est mis à jour à chaque mise en service d'une version de MIG. Si votre outillage met les schémas en cache, c'est ce fichier-là qu'il faut penser à recharger.

Ce que la structure impose — et ce qu'elle garantit

Les schémas Telebib2 sont fermés : unevaluatedProperties: false. Une propriété que le schéma ne prévoit pas n'est pas ignorée, elle provoque une erreur de validation. C'est délibéré. Dans un échange entre deux systèmes qui ne se parlent pas autrement que par ces messages, une faute de frappe silencieusement acceptée - assuredName au lieu de insuredName - coûte infiniment plus cher qu'un rejet immédiat et explicite.

Les schémas sont fermés, donc le schéma seul suffit à décider si un message est valide. Une propriété non prévue provoque une erreur, donc une faute de frappe est rejetée immédiatement au lieu d'être acceptée silencieusement. Rien ne peut être ajouté hors de metadata, donc aucune convention hors bande n'est nécessaire.
Fig. 03 - Chaque contrainte a sa contrepartie

En contrepartie, vous obtenez un message autoportant : le schéma seul suffit à décider s'il est valide, sans convention hors bande, sans documentation annexe, sans appel téléphonique.

Le message complet

Voici, assemblé, un message minimal valide - un certificat de sinistralité (M0151), réduit à ses propriétés obligatoires.

Un message M0151 minimal valide, avec trois accolades marquant les niveaux emboîtés : l'enveloppe englobe tout, le datablock commence au premier élément de dataBlocks, le contenu métier commence à content. Les deux premières propriétés du contenu forment la carte d'identité du message : le code est une chaîne, la version un entier.
Fig. 04 - Le message annoté niveau par niveau

Et le voici en entier, tel qu'il est publié dans le registre — celui-ci est valide et se copie tel quel dans votre validateur.

{
  "syntaxVersionNumber": 1,
  "senderIdentificationDetail": {
    "senderDomainAddress": "insurerA.telebib2.be"
  },
  "recipientIdentificationDetail": {
    "recipientDomainAddress": "insurerB.telebib2.be"
  },
  "dataBlocks": [
    {
      "exchangeUnitType": "contract_ExchangeUnit",
      "exchangeUnitActionCoded": "contractClaimsCertificateContractPart",
      "exchangeUnitTypeVersionNumber": "1",
      "exchangeUnitIssuingFormat": "json",
      "content": {
        "exchangeUnitBusinessContentDescription": "M0151",
        "exchangeUnitBusinessContentDescriptionVersion": 3,
        "domain": "motor",
        "mainRenewalDateInMonthDay": "06-30",
        "policyReference": {
          "referenceContent": "POL-2018-4477821"
        },
        "insurer": {
          "partyIdentification": [
            {
              "partyIdentifier": "0451",
              "codeListIdentifier": "valueSpecificToTheFsma"
            }
          ],
          "officialName": {
            "lastName": "Assurances Continentales SA"
          },
          "officialAddress": {
            "streetName": "Avenue des Arts",
            "houseNumber": "44",
            "postalCode": "1000",
            "cityName": "Bruxelles",
            "countryCode": "B"
          }
        },
        "mainPolicyHolder": {
          "officialName": {
            "lastName": "Dubois",
            "firstName": [
              "Jean"
            ]
          },
          "officialAddress": {
            "streetName": "Rue de la Loi",
            "houseNumber": "16",
            "postalCode": "1040",
            "cityName": "Etterbeek",
            "countryCode": "B"
          }
        },
        "motorisedVehicle": {
          "objectQualifier": "tractorVehicle",
          "numberPlate": {
            "referenceContent": "1-ABC-123"
          },
          "divVehicleTypeCode": "AC",
          "sasInsuredVehicleUse": "mixedUse",
          "motorThirdPartyLiabilityGuarantee": {
            "guaranteeType": "clMotor",
            "inceptionDate": "2018-07-01",
            "periodEndDate": "2026-06-30",
            "appliedBonusMalusGrade": "_11"
          }
        }
      }
    }
  ]
}

Chaque message publié dispose de deux payloads de référence dans le registre : une variante min, celle que vous venez de lire et une variante full, qui exerce toutes les propriétés du schéma. Ce sont d'excellents points de départ pour vos premiers tests et d'excellents cas de non-régression par la suite.

Contact

À propos de Telebib2