Skip to Content
Mélodium 0.10.3 is now available!
DocsExemples04. Boîte à outils JSON

Boîte à outils JSON

Source: tutorial/04_json_toolkit See in Playground

Lit un enregistrement par ligne (un mélange de valeurs JSON valides et de texte invalide), sépare les lignes invalides, classe les valides en objets JSON ou en valeurs scalaires (chaînes, nombres, booléens, tableaux), et écrit un petit résumé JSON des décomptes.

Exécution

cd tutorial/04_json_toolkit melodium run Compo.toml --input_file records.txt

Avec le fichier records.txt fourni (une chaîne, un nombre, un booléen, deux objets aux noms non-ASCII comme Saša et Örség, un tableau, et une ligne invalide), l’exemple journalise chaque enregistrement classé et écrit summary.json :

{"invalid":"1","objects":"2","scalars":"4"}

Optionnel : ajoutez --api-report et un jeton d’API (MELODIUM_API_TOKEN) pour voir la trace complète de cette exécution sur Cadence.CI.

Fonctionnement

Cet exemple n’utilise aucun modèle : l’analyse et la validation JSON sont toutes des traitements sans état.

Flux de données

Les lignes sont extraites avec split + flatten + trim, lignes vides éliminées.

Séparer les données invalides avant l’analyse

validate vérifie chaque ligne sans l’analyser ; filter répartit le flux en texte valide (accepted) et en données invalides (rejected, journalisées telles quelles) :

isValid: validate() split: filter<string>() nonBlank.accepted -> isValid.text nonBlank.accepted -> split.value isValid.is_json -> split.select logInvalid: logInfos(label="invalid") split.rejected -> logInvalid.messages

Analyse et extraction

Seul le texte valide atteint toJson, donc l’analyse ne peut jamais échouer ici. Mais toJson retourne malgré tout un Stream<Option<Json>> par construction (il n’a aucun moyen de savoir, rien qu’à partir du type, que chaque entrée est valide), d’où l’usage de unwrapOr pour obtenir un simple Stream<Json> :

parsed: toJson() asJson: unwrapOr<Json>(default=|null()) split.accepted -> parsed.text,json -> asJson.option,value -> classify.value

Vérifier la validité en amont, avec validate, évite d’avoir à gérer un échec d’analyse plus loin dans le graphe : l’Option renvoyée par toJson doit malgré tout être extraite, mais elle est garantie d’être toujours some.

Classer objets et scalaires

isObject classe chaque valeur Json ; un second filter sépare les objets des scalaires (chaînes, nombres, booléens, tableaux : tout ce qui n’est pas un objet JSON). La plupart des traitements de bibliothèque du type « est-ce que ceci satisfait X », isObject inclus, sont conçus pour se brancher directement sur filter.select :

classify: isObject() partition: filter<Json>() asJson.value -> partition.value classify.is_object -> partition.select

Construction du résumé

Trois totaux (objets, scalaires, lignes invalides) sont calculés avec un petit traitement local, finalCount<T>, utilisé ici à deux types différents (Json et string) dans le même fichier, sans changer une seule ligne de son corps. Ils sont combinés en un seul StringMap, converti en objet JSON avec fromStringMap, sérialisé avec toString<Json>, et écrit dans summary.json :

withObjects: blockEntry(key="objects") withScalars: blockInsert(key="scalars") withInvalid: blockInsert(key="invalid") objTotal.total -> withObjects.value withObjects.map -> withScalars.base scalarTotal.total -> withScalars.value withScalars.map -> withInvalid.base invalidTotal.total -> withInvalid.value summaryStream: stream<StringMap>() summaryJson: fromStringMap() summaryText: toString<Json>() write: writeTextLocal(path=output) logDone: logInfoMessage(label="json", message="summary written") withInvalid.map -> summaryStream.block,stream -> summaryJson.value,json -> summaryText.value,into -> write.text write.finished -> logDone.trigger

fromStringMap est le moyen direct de construire un objet JSON à partir de données Mélodium : chaque valeur devient une chaîne JSON, ce qui suffit pour un rapport de synthèse. Pour un JSON plus riche, avec des nombres ou des objets imbriqués, mieux vaut le construire avec les fonctions et traitements json/value::from* pris individuellement.

Dépendances

[dependencies] std = "0.10.3" # flux de base, journalisation, structures de données fs = "0.10.3" # lecture/écriture de fichiers locaux json = "0.10.3" # analyse et sérialisation JSON