Claude Code pour la correction des imports/exports de données : définissez des règles de validation, des formats d'erreur cohérents et des tests de fuzz pour les imports CSV/JSON afin de réduire les tickets support liés aux cas limites.

Les imports échouent rarement parce que le code est « incorrect ». Ils échouent parce que les données réelles sont désordonnées, incohérentes et produites par des personnes qui n'ont jamais vu vos hypothèses.
Les problèmes CSV concernent généralement la forme et le formatage. Les problèmes JSON portent souvent sur le sens et les types. Les deux peuvent casser de manières qui semblent mineures mais qui créent des résultats déroutants.
Ces problèmes reviennent sans cesse dans les tickets de support :
La correction n'est pas juste « est-ce que ça s'importe ». Vous devez décider quels résultats sont acceptables, parce que les utilisateurs remarquent les erreurs silencieuses plus que les échecs bruyants.
La plupart des équipes peuvent s'accorder sur trois issues :
Les cas limites se transforment en remaniements quand les gens ne savent pas ce qui a échoué ni comment le corriger rapidement. Scénario courant : un client téléverse un CSV de 5 000 lignes, l'importeur indique « Invalid format », et il réessaie trois fois en faisant des modifications aléatoires. Ça devient plusieurs tickets plus quelqu'un chez vous qui tente de reproduire le fichier localement.
Fixez des objectifs qui réduisent ce cycle : moins de retentatives, corrections plus rapides, résultats prévisibles. Avant d'écrire des règles, décidez ce que signifie « partiel » (et si vous l'autorisez), comment vous signalerez les problèmes au niveau ligne, et ce que l'utilisateur doit faire ensuite (éditer le fichier, mapper les champs, ou exporter une version corrigée). Si vous utilisez une plateforme de génération comme Koder.ai (koder.ai) pour créer rapidement validateurs et tests, le contrat d'import reste ce qui garantit la cohérence au fil de l'évolution du produit.
Avant d'écrire une seule règle de validation, décidez ce que signifie « entrée valide » pour votre produit. La plupart des bugs d'import viennent d'attentes non alignées entre ce que les utilisateurs téléversent et ce que votre système suppose en silence.
Commencez par les formats, et soyez explicite. « CSV » peut signifier virgule ou point-virgule, ligne d'en-tête ou non, UTF-8 ou « ce qu'Excel a produit ». Pour JSON, décidez si vous acceptez un objet unique, un tableau d'enregistrements, ou JSON Lines (un objet JSON par ligne). Si vous acceptez du JSON imbriqué, définissez quels chemins vous lisez et lesquels vous ignorez.
Ensuite verrouillez le contrat de champs. Pour chaque champ, décidez s'il est requis, optionnel, ou optionnel avec une valeur par défaut. Les valeurs par défaut font partie du contrat, pas d'un détail d'implémentation. Si country manque, mettez-vous une valeur vide, choisissez un pays par défaut, ou rejetez la ligne ?
Le comportement de parsing est l'endroit où les imports « tolérants » créent des douleurs à long terme. Décidez d'avance à quel point vous êtes strict sur le trim des espaces, la normalisation de la casse, et l'acceptation de variantes comme "yes"/"true"/"1". La tolérance est acceptable si elle est prévisible et documentée.
Les doublons sont une autre décision de contrat qui affecte la confiance. Définissez ce qui compte comme doublon (même email, même external_id, même combinaison de champs), où vous le détectez (dans le fichier, contre les données existantes, ou les deux), et ce que vous faites (conserver le premier, le dernier, fusionner, ou rejeter).
Une checklist de contrat que vous pouvez coller dans une spec :
Exemple : importer des “customers”. Si l'email est la clé unique, décidez si " [email protected] " équivaut à "[email protected]", si l'email manquant est autorisé quand external_id existe, et si les doublons dans le fichier doivent être rejetés même si la base n'a pas de correspondance. Une fois ce contrat fixé, le comportement cohérent dans l'UI et l'API est beaucoup plus simple, que vous l'implémentiez avec Koder.ai ou ailleurs.
Les imports désordonnés commencent souvent par une unique grosse fonction validate(). Une approche plus propre est d'utiliser des règles en couches avec des noms clairs et des fonctions petites. Ça facilite les revues et rend les tests plus simples à écrire.
Commencez par des règles au niveau champ : une vérification sur une seule valeur qui peut passer ou échouer seule (type, plage, longueur, valeurs autorisées, regex). Gardez-les simples et prévisibles. Exemples : email correspond à un motif d'email basique, age est un entier entre 0 et 120, status est l'un de active|paused|deleted.
Ajoutez des règles cross-field seulement quand elles importent. Ces vérifications dépendent de plusieurs champs, et les bugs s'y cachent. Exemples classiques : startDate doit être avant endDate, ou total doit équivaloir à subtotal + tax - discount. Écrivez ces règles pour qu'elles pointent des champs spécifiques, pas seulement « enregistrement invalide ».
Séparez les règles au niveau enregistrement des règles au niveau fichier. Une règle au niveau enregistrement vérifie une ligne (CSV) ou un objet (JSON). Une règle au niveau fichier vérifie l'ensemble du téléversement : les en-têtes requis existent, une clé unique ne se répète pas, le nombre de colonnes correspond, ou le fichier déclare une version supportée.
La normalisation doit être explicite, pas « magique ». Décidez ce que vous normalisez avant de valider, et documentez-le. Exemples fréquents : suppression des espaces en début/fin, normalisation Unicode (pour que des caractères visuellement identiques se comparent de la même façon), et formatage des numéros de téléphone dans un format de stockage unique.
Une structure qui reste lisible :
Versionnez vos règles. Mettez un schemaVersion (ou un profil d'import) dans le fichier ou la requête API. Quand vous changez la définition de « valide », vous pouvez toujours ré-importer d'anciennes exports en utilisant l'ancienne version. Ce simple choix évite beaucoup de tickets « ça marchait hier ».
Un bon importeur échoue de manière utile. Des erreurs vagues entraînent des retentatives aléatoires et du travail support évitable. Un format d'erreur clair aide les utilisateurs à corriger le fichier rapidement et vous permet d'améliorer la validation sans casser les clients.
Commencez par une forme d'objet d'erreur stable et gardez-la cohérente pour CSV et JSON. Vous pouvez utiliser Claude Code pour proposer un schéma et quelques exemples réalistes, puis l'officialiser comme partie du contrat d'import.
Traitez chaque erreur comme un petit enregistrement avec des champs qui ne changent pas. Le message peut évoluer, mais le code et l'emplacement doivent rester stables.
code : un identifiant court et stable comme REQUIRED_MISSING ou INVALID_DATEmessage : une phrase lisible par l'UIpath : où se situe le problème (JSON pointer comme /customer/email, ou un nom de colonne comme email)row ou line : pour CSV, inclure le numéro de ligne 1-based (et éventuellement la ligne originale)severity : au moins error et warningRendez les erreurs exploitables. Indiquez ce que vous attendiez et ce que vous avez vu, et quand possible montrez un exemple qui passerait. Par exemple : attendu YYYY-MM-DD, reçu 03/12/24.
Même si vous retournez une liste plate, incluez assez d'informations pour grouper les erreurs par ligne et par champ. Beaucoup d'interfaces veulent « Ligne 12 a 3 problèmes » puis mettre en surbrillance chaque colonne. Les équipes support aiment regrouper car des motifs apparaissent (par ex. toutes les lignes manquent country).
Une réponse compacte pourrait ressembler à :
{
"importId": "imp_123",
"status": "failed",
"errors": [
{
"code": "INVALID_DATE",
"message": "Signup date must be in YYYY-MM-DD.",
"path": "signup_date",
"row": 12,
"severity": "error",
"expected": "YYYY-MM-DD",
"actual": "03/12/24"
},
{
"code": "UNKNOWN_FIELD",
"message": "Column 'fav_colour' is not recognized.",
"path": "fav_colour",
"row": 1,
"severity": "warning"
}
]
}
Prévoyez la localisation sans changer les codes d'erreur. Gardez code indépendant de la langue et durable ; traitez message comme du texte remplaçable. Si plus tard vous ajoutez messageKey ou des messages traduits, les clients anciens peuvent toujours compter sur les mêmes codes pour filtrer, grouper et analyser.
Pour éviter les « imports mystères », la réponse de votre API doit répondre à deux questions : que s'est-il passé et que doit faire l'utilisateur ensuite.
Même quand il y a des erreurs, renvoyez un résumé cohérent pour que l'UI et les outils de support traitent chaque import de la même façon.
Incluez :
created, updated, skipped, failedtotalRows (ou totalRecords pour JSON)mode (par exemple : "createOnly", "upsert", ou "updateOnly")startedAt et finishedAtcorrelationId que le support peut demanderCe correlationId en vaut la peine. Quand quelqu'un signale « ça ne s'est pas importé », vous pouvez trouver l'exécution exacte et le rapport d'erreurs sans deviner.
Ne renvoyez pas 10 000 erreurs de lignes dans la réponse. Retournez un petit échantillon (par ex. 20) qui montre le motif, et fournissez un moyen séparé pour récupérer le rapport complet si nécessaire.
Faites chaque erreur spécifique et stable :
Exemple de forme de réponse (succès avec quelques lignes échouées) :
{
"importId": "imp_01HZY...",
"correlationId": "c_9f1f2c2a",
"status": "completed_with_errors",
"summary": {
"totalRows": 1200,
"created": 950,
"updated": 200,
"skipped": 10,
"failed": 40
},
"errorsSample": [
{
"row": 17,
"field": "email",
"code": "invalid_format",
"message": "Email must contain '@'.",
"value": "maria.example.com"
}
],
"report": {
"hasMore": true,
"nextPageToken": "p_002"
},
"next": {
"suggestedAction": "review_errors"
}
}
Remarquez le champ next. Même une charge minimale devrait aider le produit à avancer : afficher un écran de revue, proposer une ré-essai, ou ouvrir la collection importée.
Les gens retentent. Les réseaux tombent. Si le même fichier est importé deux fois, vous voulez un résultat prévisible.
Soyez explicite sur l'idempotence : acceptez un idempotencyKey (ou calculez un hash de fichier), et renvoyez le même importId si la requête est un doublon. Si votre mode est upsert, définissez la règle de correspondance (par exemple, « email est la clé unique »). Si c'est create-only, renvoyez « skipped » pour les doublons, pas « created again ».
Si la requête entière est invalide (mauvaise auth, mauvais content-type, fichier illisible), échouez vite et renvoyez status: "rejected" avec une petite liste d'erreurs. Si le fichier est valide mais contient des problèmes au niveau ligne, traitez-le comme un job complété avec failed > 0 afin que les utilisateurs puissent corriger et retéléverser sans perdre le résumé.
Bonne pratique : faites écrire au modèle le contrat sous une forme structurée, pas en prose. Les paragraphes « utiles » sautent souvent des détails comme les règles de trim, les valeurs par défaut, et si une cellule vide signifie « manquante » ou « vide ».
Utilisez un prompt qui force un tableau que l'humain peut relire vite et que le développeur peut transformer en code. Demandez pour chaque champ sa règle, des exemples qui passent et d'échouement, et une note explicite pour toute ambiguïté (par ex. chaîne vide vs null).
You are helping design an importer for CSV and JSON.
Output a Markdown table with columns:
Field | Type | Required? | Normalization | Validation rules | Default | Pass examples | Fail examples
Rules must be testable (no vague wording).
Then output:
1) A list of edge cases to test (CSV + JSON).
2) Proposed test names with expected result (pass/fail + error code).
Finally, list any contradictions you notice (required vs default, min/max vs examples).
Après le premier jet, resserrez en demandant un exemple positif et un exemple négatif par règle. Cela pousse la couverture des coins difficiles comme chaînes vides, valeurs uniquement d'espaces, colonnes manquantes, null vs "null", très grands entiers, notation scientifique, IDs dupliqués, et champs JSON supplémentaires.
Pour un scénario concret, imaginez l'import de “customers” depuis CSV : email est requis, phone est optionnel, et signup_date a pour défaut la date du jour si manquante. Le modèle devrait signaler une contradiction si vous dites aussi que signup_date est requis. Il devrait proposer des tests comme import_customers_missing_email_returns_row_error et spécifier le code d'erreur et la forme du message que vous renvoyez.
Faites une passe supplémentaire avant l'implémentation : demandez au modèle de reformuler les règles sous forme de checklist et de pointer où les défauts, champs requis et normalisations pourraient être en conflit. Cette étape de revue attrape beaucoup de comportements sources de tickets.
Les tests de fuzz empêchent que des « fichiers bizarres » deviennent des tickets de support. Commencez par un petit ensemble de fichiers valides, puis générez des milliers de variations légèrement brisées et assurez-vous que votre importeur réagit de manière sûre et claire.
Commencez par un petit corpus d'exemples valides représentant l'usage réel : le plus petit fichier valide, un fichier typique, et un gros fichier. Pour JSON, incluez un objet unique, de nombreux objets, et des structures imbriquées si vous les supportez.
Ajoutez ensuite un mutateur automatisé qui modifie une chose à la fois. Gardez les mutations reproductibles en consignant la graine aléatoire pour pouvoir rejouer les échecs.
Dimensions de fuzz qui captent la plupart des problèmes réels :
Ne vous arrêtez pas à la syntaxe. Ajoutez aussi du fuzz sémantique : permutez des champs proches (email vs username), dates extrêmes, IDs dupliqués, quantités négatives, ou valeurs violant des enums.
Les tests de fuzz n'aident que si les critères de réussite sont stricts. Votre importeur ne doit jamais planter et les erreurs doivent être cohérentes et exploitables.
Un ensemble pratique de règles de réussite :
Exécutez ces tests en CI à chaque changement. Quand vous trouvez un échec, conservez le fichier exact comme fixture et ajoutez un test de régression pour qu'il ne réapparaisse plus.
Si vous utilisez Claude Code pour ce travail, faites-lui générer des fixtures seed qui correspondent à votre contrat, un plan de mutation et les sorties d'erreur attendues. Vous choisissez toujours les règles, mais vous gagnez rapidement une large surface de tests, notamment pour les guillemets CSV et les coins JSON.
La plupart des tickets d'import viennent de règles floues et de retours peu utiles.
Un piège fréquent est le parsing en « best effort » qui n'est pas documenté. Si votre importeur enlève silencieusement les espaces, accepte virgule et point-virgule, ou devine les formats de date, les utilisateurs vont construire des workflows sur ces suppositions. Puis un petit changement, ou un autre générateur de fichiers, casse tout. Choisissez le comportement, documentez-le et testez-le.
Autre coupable récurrent : le message d'erreur générique. « Invalid CSV » ou « Bad request » force l'utilisateur à deviner. Ils téléversent le même fichier cinq fois, et le support demande finalement le fichier. Les erreurs doivent pointer une ligne, un champ, une raison claire, et un code d'erreur stable.
Rejeter tout le fichier pour une mauvaise ligne est aussi souvent problématique. Parfois c'est correct (imports financiers où les données partielles sont dangereuses). Beaucoup d'importations métier peuvent continuer et rapporter un résumé, tant que vous proposez une option explicite comme mode strict vs import partiel.
Les problèmes d'encodage de texte génèrent des tickets tenaces. UTF-8 est le bon défaut, mais les CSV réels incluent souvent un BOM, des guillemets courbes, ou des espaces insécables copiés depuis des tableurs. Gérez-les de façon cohérente et indiquez ce que vous avez détecté pour que les utilisateurs modifient leurs paramètres d'export.
Enfin, changer les codes d'erreur entre les versions casse les clients et les automatisations. Améliorez le libellé si vous voulez, mais conservez les codes et significations stables. Versionnez-les uniquement si nécessaire.
Pièges à prévenir dès le départ :
Exemple : un client exporte un CSV depuis Excel, qui ajoute un BOM et formate des dates en 03/04/2026. Votre importeur devine MM/DD, mais le client attend DD/MM. Si votre rapport d'erreur indique le format détecté, le champ exact et une correction suggérée, l'utilisateur peut corriger sans aller-retour.
La plupart des problèmes d'import sont de petits désalignements entre ce que les utilisateurs pensent que signifie le fichier et ce que votre système accepte. Traitez ceci comme une condition de mise en production.
Un test pratique : utilisez un fichier volontairement désordonné. Ex : un CSV où l'en-tête apparaît deux fois (deux colonnes “email”), un champ booléen utilise “Y”, et une date est “03/04/05”. Votre importeur ne doit pas deviner. Il doit soit appliquer une règle de mapping documentée, soit rejeter avec une erreur spécifique.
Deux vérifications souvent négligées :
Premièrement, vérifiez que votre importeur rapporte des erreurs avec suffisamment de détails de localisation pour corriger le fichier source. “Invalid date” n'est pas exploitable. “Ligne 42, colonne start_date : attendu YYYY-MM-DD, reçu 03/04/05” l'est.
Deuxièmement, exécutez le même fichier invalide deux fois et comparez les résultats. Si l'ordre des erreurs change, les codes changent, ou les numéros de ligne dérivent, les utilisateurs perdent confiance. Un comportement déterministe est ennuyeux, et c'est le but.
Un import courant est des commandes clients provenant d'un export de tableur. Quelqu'un exporte un CSV depuis un ancien système, l'édite dans Excel, puis le téléverse. La plupart des tickets surviennent quand l'importeur « corrige » silencieusement les données ou quand le message d'erreur n'explique pas quoi changer.
Imaginez un fichier nommé orders.csv avec les colonnes : order_id,customer_email,order_date,currency,total_amount.
Voici trois lignes erronées réalistes (telles que l'utilisateur les verrait) :
order_id,customer_email,order_date,currency,total_amount
A-1001,[email protected],2026-01-05,USD,129.99
A-1002,not-an-email,01/06/2026,USD,49.00
,[email protected],2026-01-07,US, -10
La ligne 2 a un email invalide et un format de date ambigu. La ligne 3 manque order_id, a un code devise non supporté (US au lieu de USD), et un montant négatif.
Si votre API renvoie des erreurs, gardez la forme cohérente et spécifique. Voici un exemple de réponse supportant le succès partiel :
{
"correlation_id": "imp_20260109_7f3a9d",
"import_id": "ord_01HZZ...",
"status": "partial_success",
"summary": {
"total_rows": 3,
"imported_rows": 1,
"failed_rows": 2
},
"errors": [
{
"row_number": 2,
"field": "customer_email",
"code": "invalid_email",
"message": "Email must contain a valid domain.",
"value": "not-an-email"
},
{
"row_number": 2,
"field": "order_date",
"code": "invalid_date_format",
"message": "Use ISO-8601 (YYYY-MM-DD).",
"value": "01/06/2026"
},
{
"row_number": 3,
"field": "order_id",
"code": "required",
"message": "order_id is required.",
"value": ""
},
{
"row_number": 3,
"field": "currency",
"code": "unsupported_currency",
"message": "Allowed values: USD, EUR, GBP.",
"value": "US"
},
{
"row_number": 3,
"field": "total_amount",
"code": "must_be_positive",
"message": "total_amount must be greater than 0.",
"value": " -10"
}
],
"retry": {
"mode": "upload_failed_only",
"failed_row_numbers": [2, 3]
}
}
Le succès partiel est important car les utilisateurs ne doivent pas retéléverser tout le fichier. Un flux de ré-essai simple : corriger seulement les lignes échouées, exporter un petit CSV contenant les lignes 2 et 3, puis retéléverser. Votre importeur doit traiter cela comme idempotent quand order_id est présent, de sorte que le « retry » mette à jour les mêmes enregistrements au lieu d'en créer des doublons.
Pour le support, correlation_id est le chemin le plus rapide pour diagnostiquer. Un agent peut demander cette valeur, trouver l'exécution dans les logs, et confirmer si le parseur a vu des colonnes en plus, un mauvais délimiteur, ou un encodage inattendu.
Prochaines étapes pour rendre cela répétable :
La plupart des échecs proviennent de données du monde réel, pas d'un « mauvais code ». Les problèmes CSV concernent généralement la forme (en-têtes, délimiteur, guillemets, encodage), tandis que les problèmes JSON portent souvent sur la signification (types, null vs vide, imbrication inattendue). Traitez les deux comme des entrées non fiables et validez-les par rapport à un contrat explicite.
Définissez trois issues possibles dès le départ :
Choisissez un comportement par défaut (beaucoup de produits choisissent le mode partiel) et appliquez-le de manière cohérente dans l'UI et l'API.
Rédigez un contrat d'import avant d'écrire la validation :
Cela évite les surprises du type « ça marchait hier ».
Privilégiez un format non ambigu par champ (par exemple, dates en YYYY-MM-DD). Si vous acceptez des variantes, spécifiez-les de manière prévisible (par exemple true/false/1/0), mais n'acceptez pas toutes les déductions des tableurs. Évitez de deviner des dates ambigües comme 01/02/03 : exigez l'ISO ou rejetez avec une erreur claire.
Décidez :
Combinez cela avec l'idempotence : si les utilisateurs retentent, l'import ne doit pas créer de doublons.
Utilisez des couches plutôt qu'une grosse fonction validate() :
Retournez une forme d'erreur stable avec :
Toujours renvoyer un résumé cohérent, même en cas d'erreurs :
Supportez les relances explicitement :
idempotencyKey (ou utilisez le hash du fichier)importId si la requête est répétéeSinon, les retentatives normales risquent de créer des doublons.
Commencez avec quelques fichiers seed valides, puis générez des mutations petites et reproductibles (une modification à la fois) :
NaN/Infinity en JSON)Un test de fuzz « passe » si l'importeur ne plante pas/accroche et renvoie des erreurs déterministes et exploitables.
Des règles petites et nommées sont plus simples à tester et à faire évoluer.
code (identifiant stable)message (lisible par un humain)path/field (nom de colonne ou pointer JSON)row/line (pour CSV)severity (error vs warning)Rendez l'erreur exploitable en indiquant ce qui était attendu et ce qui a été reçu quand c'est possible.
created, updated, skipped, failed, plus totalRows/totalRecordsstatus (success, rejected, completed_with_errors)startedAt, finishedAt)correlationId pour le support et le débogagePour les gros fichiers, fournissez un errorsSample et un moyen de récupérer le rapport complet.