Sélectionnez votre langue

Hints & tips

Écrire et valider

Hints & tips : les erreurs des premières semaines

Rien ici n'est difficile. Ce sont des détails : un type, un format, une valeur qui ne ressemble pas à ce qu'on attendait. Mais chacun coûte facilement une demi-journée à celui qui le rencontre sans être prévenu. Autant l'être.

Les types qui piègent

La version du MIG est un entier. exchangeUnitBusinessContentDescriptionVersion vaut 3, pas "3". Le code du message, lui, est bien une chaîne. Cette dissymétrie surprend et c'est de loin l'erreur la plus fréquente au premier essai (d'autant que l'erreur remonte du routeur, donc en tête de cascade, avec un message peu parlant).

Les valeurs à virgule sont des chaînes. Un montant s'écrit "1234.56". Le réflexe de sérialiser un decimal en nombre JSON est si naturel qu'il passe souvent inaperçu jusqu'à la première validation.

Les comptages, eux, restent des nombres. Un nombre d'assurés est un entier JSON. La règle est simple : à virgule, c'est une chaîne ; entier, c'est un nombre.

Correct

{

  "exchangeUnitBusinessContentDescription": "M0151",

  "exchangeUnitBusinessContentDescriptionVersion": 3,

  "premiumAmount": "1234.56",

  "numberOfInsuredPersons": 3

}

Rejeté

{

  "exchangeUnitBusinessContentDescription": "M0151",

  "exchangeUnitBusinessContentDescriptionVersion": "3",

  "premiumAmount": 1234.56,

  "numberOfInsuredPersons": "3"

}
Les types qui piègent. Le code du message, exchangeUnitBusinessContentDescription, est une chaîne, mais son numéro de version, exchangeUnitBusinessContentDescriptionVersion, est un entier : deux propriétés au même préfixe, deux types différents, de loin l'erreur la plus fréquente au premier essai. La règle générale : une valeur à virgule, comme un montant, s'écrit en chaîne ; un entier, comme un comptage, reste un nombre.
Fig. 01 — Les types qui piègent

Les valeurs de listes ne sont pas toutes lisibles

Les listes arbitrées par Telebib2 portent des valeurs en toutes lettres : "motor", "naturalPerson", "valueSpecificToTheFsma". C'est le cas de l'immense majorité d'entre elles.

Mais les listes officielles (celles qui viennent de la FSMA, de la DIV, de la nomenclature NACE) sont reprises telles quelles, codes compris. Le code pays de la Belgique est "B" et non "BE" : ce n'est pas de l'ISO 3166. Un type de carburant est "1", une chaîne contenant un chiffre.

Ces deux familles s'écrivent aussi différemment dans les schémas : enum avec des libellés bilingues pour les listes Telebib, oneOf avec un titre pour les listes officielles. Si vous générez du code à partir des schémas, votre générateur doit savoir traiter les deux formes.

Liste Telebib = enum lisible

{

  "type": "string",

  "enum": ["clMotor", "clFire", "clFamily"],

  "x-enum-labels": {

    "clMotor": { "fr": "Auto", "nl": "Auto" }

  }

}

Liste officielle = oneOf, codes d'origine

{

  "type": "string",

  "oneOf": [

    { "const": "B",  "title": "Belgium" },

    { "const": "F",  "title": "France" },

    { "const": "NL", "title": "Netherlands" }

  ]

}
Trois surprises dans les valeurs de listes. Le code pays de la Belgique est B et non BE : ce n'est pas de l'ISO 3166. Un type de carburant vaut 1, une chaîne qui contient un chiffre. Une valeur commençant par un underscore n'est pas une faute : _11 est le degré bonus-malus 11. L'immense majorité des listes portent des valeurs lisibles ; ce sont les exceptions qui font perdre du temps.
Fig. 02 — Trois surprises dans les valeurs de listes

Les dates ont trois formes

Une date de prise d'effet est une date complète, au format ISO AAAA-MM-JJ. Un horodatage d'émission est une date-heure. Mais certaines propriétés portent une date partielle et c'est là qu'on se fait avoir.

L'échéance principale d'un contrat, par exemple, est un mois et un jour sans année : "06-30" pour le 30 juin. C'est logique car l'échéance revient chaque année, mais ce n'est pas une date que votre bibliothèque saura désérialiser toute seule.

Il existe de même des propriétés qui ne portent qu'une année, ou qu'une année et un mois. Vérifiez le type dans le schéma plutôt que de supposer : les trois formes se ressemblent assez pour être confondues et assez peu pour ne pas valider.

Quatre formes, quatre motifs

{

  "inceptionDate": "2018-07-01",

  "exchangeUnitIssueDateTime": "2026-08-31T09:15:00Z",

  "mainRenewalDateInMonthDay": "06-30",

  "constructionYear": "1997"

}
Quatre formes de date, quatre motifs. Une date complète s'écrit au format ISO année-mois-jour, par exemple 2018-07-01. Un horodatage s'écrit au format ISO 8601 complet, par exemple 2026-08-31T09:15:00Z. Certaines propriétés portent une date partielle : un mois et un jour sans année, comme 06-30 pour une échéance annuelle, ou une année seule, comme 1997. Ces formes se ressemblent assez pour être confondues, assez peu pour valider, et ne se désérialisent pas toutes seules.
Fig. 03 — Quatre formes de date, quatre motifs

Les longueurs sont contraintes

Beaucoup de chaînes ont une longueur maximale, héritée des largeurs de champ d'EDIFACT. Une adresse de domaine s'arrête à 35 caractères, une référence libre d'unité d'échange à 17, le contenu d'une référence à 40.

Ces bornes se rappellent au mauvais moment : votre identifiant de corrélation interne fait 24 caractères, il passe très bien en test et casse le jour où quelqu'un y ajoute un préfixe d'environnement. Vérifiez-les à la conception, pas à la recette.

Symétriquement, beaucoup de chaînes ont un minLength de 1 : une chaîne vide n'est pas une valeur absente. Si vous n'avez rien à transmettre, omettez la propriété, ne la remplissez pas d'une chaîne vide.

Absent plutôt que vide

{ "senderUserAddress": "" }     // rejeté

{ }                             // correct
Quelques plafonds à connaître. Une adresse de domaine s'arrête à 35 caractères, une référence libre d'unité d'échange à 17, le contenu d'une référence à 40. Ces bornes sont héritées des largeurs de champ d'EDIFACT et se rappellent au mauvais moment, quand un préfixe d'environnement s'ajoute à un identifiant qui passait en test. Symétriquement, beaucoup de chaînes ont un minLength de 1 : une chaîne vide n'est pas une valeur absente, il faut omettre la propriété.
Fig. 04 — Les longueurs sont contraintes

L'objet vide qui passe la validation

Voici un cas plus subtil et il mérite qu'on s'y arrête. Certains objets du modèle n'ont aucune propriété obligatoire : un intermédiaire, un preneur d'assurance dans certains messages. Un objet vide y est donc parfaitement valide : "intermediary": {} passe la validation sans réserve.

C'est correct au sens du schéma et vide de sens au sens métier. Le validateur ne peut rien pour vous ici : il vérifie une forme, pas une intention.

La conséquence pratique : si votre code construit ses objets avant de savoir s'il aura des données à y mettre, vous produirez des objets vides que rien ne signalera. Le registre surveille ce motif sur ses propres payloads de référence et distingue les cas attendus des autres. C'est un contrôle qui vaut la peine d'être repris chez vous.

Valide et pourtant probablement un bug

{

  "content": {

    "exchangeUnitBusinessContentDescription": "M0105",

    "exchangeUnitBusinessContentDescriptionVersion": 7,

    "intermediary": {},

    "mainPolicyHolder": {}

  }

}
L'objet vide qui passe la validation. Certains objets du modèle, un intermédiaire ou un preneur d'assurance dans certains messages, n'ont aucune propriété obligatoire : un objet vide y est parfaitement valide au sens du schéma, et vide de sens au sens métier. Le validateur vérifie une forme, pas une intention. Un code qui construit ses objets avant de savoir s'il aura des données à y mettre produit des objets vides que rien ne signale.
Fig. 05 — L'objet vide qui passe la validation

Les réflexes qui font gagner du temps

Partez du payload full, pas de zéro. Il exerce toutes les propriétés du schéma. Retirer ce dont vous n'avez pas besoin est plus rapide, et plus sûr, que de deviner ce qu'il faut ajouter.

Rechargez le routeur, pas le reste. Les fichiers de version sont immuables et se mettent en cache sans limite. schemaRouter.json change à chaque mise en service : c'est le seul à invalider.

Vérifiez le couple message + version en premier. Quand une erreur incompréhensible arrive en tête de cascade, c'est presque toujours que le routeur ne reconnaît pas le message annoncé.

Épinglez vos schémas. Miroitez le registre plutôt que de le déréférencer en production et notez la version du registre avec laquelle vous validez. Le jour où un comportement change, vous saurez entre quelles versions chercher.

Les quatre réflexes qui font gagner du temps. Partez du payload full plutôt que de zéro. Rechargez le routeur, pas le reste : les fichiers de version sont immuables et se cachent sans limite, seuls schemaRouter.json et compatibility.json changent. Vérifiez le couple message et version en premier. Épinglez vos schémas en miroitant le registre et en notant sa version. Aucun de ces points n'est une difficulté de conception : ce sont des conventions, et une convention ne se devine pas.
Fig. 06 — Les quatre réflexes qui font gagner du temps
Le check-list du premier message, six points à vérifier : un validateur en draft 2020-12, des schémas enregistrés localement, la version du MIG en entier, les décimaux en chaînes, aucune chaîne vide, et le payload full validé de bout en bout.
Fig. 07 — Le check-list du premier message

Aucun de ces points n'est une difficulté de conception : ce sont des conventions et une convention ne se devine pas. Une fois passées les deux premières semaines, elles deviennent invisibles. C'est précisément pour raccourcir ces deux semaines que cette page existe.

Contact

À propos de Telebib2