8 min

Claude Code per la correttezza di import/export dati: passaggi pratici

Claude Code per la correttezza import/export dati: definisci regole di validazione, formati di errore coerenti e fuzz test per import CSV/JSON per ridurre i ticket su casi limite.

Claude Code per la correttezza di import/export dati: passaggi pratici

Cosa va storto con gli import CSV e JSON

Gli import raramente falliscono perché il codice è “sbagliato”. Falliscono perché i dati reali sono disordinati, incoerenti e prodotti da persone che non conoscono le tue assunzioni.

I problemi CSV riguardano di solito la forma e il formato. I problemi JSON riguardano più spesso il significato e i tipi. Entrambi possono rompersi in modi che sembrano minori ma creano risultati confusi.

Questi problemi riappaiono continuamente nei ticket di supporto:

  • Campi richiesti mancanti (email, id, country) o colonne rinominate da qualcuno che «pulisce» il file
  • Date strane (01/02/03, 2024-13-01, numeri seriali di Excel, fusi orari misti)
  • Colonne extra o oggetti JSON nidificati inattesi aggiunti da un altro strumento
  • Drift dei tipi ("00123" diventa 123, true/false diventa "yes"/"no")
  • Duplicati e quasi duplicati (stesso id due volte, o la stessa persona con differente maiuscole)

La correttezza non è solo “è stato importato”. Devi decidere quali esiti sono permessi, perché gli utenti notano gli errori silenziosi più dei fallimenti rumorosi.

La maggior parte dei team può accordarsi su tre esiti:

  • Accepted: tutte le righe o i record sono validi e vengono importati
  • Rejected: niente viene importato perché il file non è affidabile (header sbagliati, encoding errato, JSON illeggibile)
  • Partially accepted: i record validi vengono importati, quelli non validi vengono saltati con motivazioni chiare

I casi limite diventano rielaborazioni quando le persone non capiscono cosa è andato storto o come correggerlo rapidamente. Uno scenario comune: un cliente carica un CSV di 5.000 righe, l'importer dice “Invalid format”, e riprova tre volte con modifiche casuali. Questo genera più ticket più qualcuno dalla tua parte che cerca di riprodurre il file in locale.

Fissa obiettivi che riducano il ciclo: meno retry, correzioni più veloci, risultati prevedibili. Prima di scrivere regole, decidi cosa significa “parziale” (e se lo permetti), come riporterai i problemi a livello di riga e cosa dovrebbe fare l'utente dopo (modificare il file, mappare i campi o esportare una versione corretta). Se usi una piattaforma tipo Koder.ai (koder.ai) per generare rapidamente validator e test, il contratto di import rimane comunque ciò che mantiene il comportamento coerente man mano che il prodotto evolve.

Decidi il contratto di import prima di scrivere le regole

Prima di scrivere una singola regola di validazione, decidi cosa significa “input valido” per il tuo prodotto. La maggior parte dei bug di import sono aspettative disallineate tra ciò che gli utenti caricano e ciò che il sistema assume silenziosamente.

Inizia dai formati, e sii esplicito. “CSV” può significare virgola o punto e virgola, riga di header o no, UTF-8 o “quello che ha prodotto Excel”. Per JSON, decidi se accetti un singolo oggetto, un array di record o JSON Lines (un oggetto JSON per riga). Se accetti JSON nidificato, definisci quali path leggi e quali ignori.

Poi blocca il contratto dei campi. Per ogni campo, decidi se è required, optional, o optional con default. I default sono parte del contratto, non un dettaglio di implementazione. Se country manca, fai il default a vuoto, scegli un paese specifico o rigetti la riga?

Il comportamento di parsing è dove gli import “tolleranti” creano dolore a lungo termine. Decidi in anticipo quanto sei severo nel rimuovere spazi, normalizzare le maiuscole e accettare varianti come "yes"/"true"/"1". La tolleranza va bene se è prevedibile e documentata.

I duplicati sono un'altra decisione di contratto che influenza correttezza e fiducia. Definisci cosa conta come duplicato (stessa email, stesso external_id, o la stessa combinazione di campi), dove lo rilevi (all'interno del file, contro i dati esistenti, o entrambi), e cosa fai quando succede (keep first, keep last, merge, o reject).

Una checklist di contratto che puoi incollare in una spec:

  • Formati e encoding accettati (delimitatore CSV, JSON vs JSON Lines, supporto nidificato)
  • Regole dei campi (required/optional/default, valori ammessi)
  • Regole di normalizzazione (trim, case, formati di date/numeri)
  • Definizione e gestione dei duplicati (ambito di rilevamento, comportamento scelto)
  • Posizionamento della validazione (client, server o entrambi)

Esempio: importare “customers”. Se l'email è la chiave unica, decidi se " [email protected] " è uguale a "[email protected]", se l'email mancante è consentita quando esiste external_id, e se i duplicati all'interno del file devono essere rifiutati anche se il database non ha corrispondenze. Una volta fissato questo contratto, il comportamento coerente tra UI e API è molto più semplice, sia che tu lo implementi in Koder.ai sia altrove.

Regole di validazione leggibili e testabili

I import disordinati spesso iniziano con un unico enorme validate(). Un approccio più pulito è usare regole stratificate con nomi chiari e funzioni piccole. Questo rende le modifiche più facili da revisionare e i test più semplici da scrivere.

Inizia con regole a livello di campo: verifiche che un singolo valore possa passare o fallire da solo (tipo, range, lunghezza, valori ammessi, regex). Mantienile noiose e prevedibili. Esempi: email corrisponde a un pattern email di base, age è un intero tra 0 e 120, status è uno di active|paused|deleted.

Aggiungi regole cross-field solo dove contano. Questi controlli dipendono da più campi, e i bug si nascondono qui. Esempi classici: startDate deve essere prima di endDate, o total deve essere uguale a subtotal + tax - discount. Scrivi queste regole in modo che possano indicare campi specifici, non solo “record invalid”.

Separa le regole a livello di record da quelle a livello di file. Una regola record-level controlla una riga (CSV) o un oggetto (JSON). Una regola file-level controlla tutto l'upload: header richiesti esistono, una chiave unica non si ripete tra le righe, il numero di colonne corrisponde alle aspettative, o il file dichiara una versione supportata.

La normalizzazione dovrebbe essere esplicita, non “magica”. Decidi cosa normalizzi prima di validare e documentalo. Esempi comuni includono trim degli spazi, normalizzazione Unicode (così caratteri visivamente identici sono confrontati allo stesso modo) e formattazione dei numeri di telefono in un formato coerente di memorizzazione.

Una struttura che resta leggibile:

  • Normalize: trasforma l'input grezzo in una forma canonica.
  • Validate fields: controlli piccoli e riutilizzabili per campo.
  • Validate relationships: controlli cross-field con target chiari.
  • Validate file rules: header, duplicati e supporto versione.
  • Test each layer: test unitari per ogni regola, più alcuni fixture end-to-end.

Versiona le tue regole. Metti un schemaVersion (o un profilo di import) nel file o nella richiesta API. Quando cambi cosa significa “valido”, puoi ancora re-importare esportazioni vecchie usando la versione precedente. Questa scelta evita molti ticket “funzionava ieri”.

Progetta un formato di error reporting che le persone possano usare

Un buon importer fallisce in modo utile. Messaggi vaghi portano a retry casuali e lavoro di supporto evitabile. Un formato di errore chiaro aiuta gli utenti a correggere il file rapidamente e ti aiuta a migliorare la validazione senza rompere i client.

Inizia con una forma stabile dell'oggetto errore e mantienila coerente tra CSV e JSON. Puoi usare Claude Code per proporre uno schema e alcuni esempi realistici, poi fissarlo come parte del contratto di import.

Un oggetto errore stabile

Tratta ogni errore come un piccolo record con campi che non cambiano. Il message può evolvere, ma il codice e la location devono rimanere stabili.

  • code: un identificatore corto e stabile come REQUIRED_MISSING o INVALID_DATE
  • message: una frase leggibile dall'utente per la UI
  • path: dove si trova il problema (JSON pointer come /customer/email, o un nome colonna come email)
  • row o line: per CSV, includi il numero di riga 1-based (e opzionalmente la riga originale)
  • severity: almeno error e warning

Rendi gli errori azionabili. Includi cosa ti aspettavi e cosa hai effettivamente visto, e quando possibile mostra un esempio che passerebbe. Per esempio: expected YYYY-MM-DD, got 03/12/24.

Raggruppamento per UI e debugging

Anche se ritorni una lista piatta, includi dati sufficienti per raggruppare errori per riga e per campo. Molte UI vogliono “Riga 12 ha 3 problemi” e poi evidenziare ogni colonna. I team di supporto apprezzano il raggruppamento perché i pattern diventano ovvi (per esempio, ogni riga manca country).

Una risposta compatta potrebbe sembrare così:

{
  "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"
    }
  ]
}

Pianifica la localizzazione senza cambiare i code degli errori. Mantieni code neutrale rispetto alla lingua e durevole, e tratta message come testo sostituibile. Se in seguito aggiungi messageKey o messaggi tradotti, i client vecchi possono comunque affidarsi agli stessi codici per filtrare, raggruppare e fare analytics.

Cosa dovrebbe restituire l'API di import in caso di successo e di errore

Deploy your import pipeline
Move from prototype to deployment and hosting when your importer is ready to ship.

Per evitare “import misteriosi”, la risposta della tua API dovrebbe rispondere a due domande: cosa è successo e cosa dovrebbe fare l'utente dopo.

Restituisci sempre un riepilogo di import (ogni volta)

Anche quando ci sono errori, restituisci un riepilogo coerente così UI e strumenti di supporto possono gestire ogni import allo stesso modo.

Includi:

  • conteggi created, updated, skipped, failed
  • totalRows (o totalRecords per JSON)
  • mode (per esempio: "createOnly", "upsert" o "updateOnly")
  • timestamp startedAt e finishedAt
  • un correlationId che il supporto può richiedere

Quel correlationId vale molto. Quando qualcuno segnala “non è stato importato”, puoi trovare l'esecuzione esatta e il report degli errori senza indovinare.

Includi errori azionabili e un modo per recuperare il report completo

Non riversare 10.000 errori di riga nella risposta. Restituisci un piccolo campione (per esempio 20) che mostri il pattern e fornisci un modo separato per recuperare il report completo se necessario.

Rendi ogni errore specifico e stabile:

  • location: numero di riga (CSV) o path in stile JSON pointer (JSON)
  • nome del campo
  • codice errore (leggibile a macchina)
  • messaggio (leggibile dall'utente)
  • valore rifiutato (attenzione ai dati sensibili)

Esempio di forma di risposta (successo con alcuni fallimenti di riga):

{
  "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"
  }
}

Nota il campo next. Anche un payload minimo di successo dovrebbe aiutare il prodotto a procedere: mostrare una schermata di revisione, offrire un retry o aprire la raccolta importata.

Definisci l'idempotenza così upload ripetuti non generano duplicati

Le persone ritentano. Le reti falliscono. Se lo stesso file viene importato due volte, vuoi risultati prevedibili.

Sii esplicito sull'idempotenza: accetta un idempotencyKey (o calcola un hash del file) e restituisci lo stesso importId se la richiesta è una ripetizione. Se la modalità è upsert, definisci la regola di matching (per esempio, “email è la chiave unica”). Se è create-only, per i duplicati restituisci “skipped” e non “created again”.

Usa lo status giusto per i fallimenti, ma mantieni la forma stabile

Se la richiesta è invalida (auth mancante, content type sbagliato, file illeggibile), fallisci subito e restituisci status: "rejected" con una breve lista di errori. Se il file è valido ma ha problemi a livello di riga, trattalo come un job completato con failed > 0 così gli utenti possono correggere e ricaricare senza perdere il riepilogo.

Come usare Claude Code per generare regole ed esempi

Un'abitudine utile: fai scrivere al modello il contratto in un formato strutturato, non in prosa. Le “frasi utili” spesso saltano dettagli come regole di trim, valori default e se una cella vuota significa “missing” o “empty”.

Usa un prompt che forzi una tabella che un umano può revisionare rapidamente e uno sviluppatore può trasformare in codice. Chiedi per ogni campo la regola, esempi di pass e fail, e una nota esplicita per qualsiasi ambiguità (per esempio, empty string 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).

Dopo la prima bozza, stringila chiedendo un esempio positivo e uno negativo per regola. Questo spinge la copertura di angoli difficili come stringhe vuote, valori fatti solo di spazi, colonne mancanti, null vs "null", interi molto grandi, notazione scientifica, ID duplicati e campi JSON extra.

Per uno scenario concreto, immagina di importare “customers” da CSV: email è richiesto, phone è opzionale e signup_date di default è oggi se mancante. Il modello dovrebbe segnalare una contraddizione se dichiari anche “signup_date è obbligatorio”. Dovrebbe proporre test come import_customers_missing_email_returns_row_error e specificare il codice errore e la forma del messaggio che restituisci.

Fai un altro passaggio prima dell'implementazione: chiedi al modello di ripetere le regole come checklist e indicare dove default, campi obbligatori e normalizzazione potrebbero entrare in conflitto. Questo step di revisione cattura molti comportamenti che genererebbero ticket.

Passo dopo passo: fuzz test per import CSV e JSON

Generate validation rules
Describe your fields and edge cases, and let Koder.ai generate validators and unit tests.

I fuzz test fermano i “file strani” dal diventare ticket di supporto. Parti da un piccolo set di file validi, poi genera migliaia di variazioni leggermente difettose e assicurati che il tuo importer reagisca in modo sicuro e chiaro.

Costruisci un seed set, poi mutalo

Inizia con un piccolo corpus di esempi validi che rappresentino l'uso reale: il file valido più piccolo, un file tipico e un file grande. Per JSON, includi un oggetto singolo, molti oggetti e strutture nidificate se le supporti.

Poi aggiungi un mutator automatizzato che modifica una cosa per volta. Mantieni le mutazioni riproducibili loggando il seed random così puoi riprodurre i fallimenti.

Dimensioni di fuzz che catturano la maggior parte dei problemi reali:

  • Problemi di encoding: UTF-8 con BOM, sequenze di byte invalide, normalizzazione mista
  • Problemi di struttura: header mancanti, colonne/field extra, delimitatore sbagliato, virgole finali
  • Quoting e newline: virgolette non chiuse, newline incorporati, CRLF vs LF, escaping incoerente
  • Edge dei tipi: interi enormi, NaN/Infinity (JSON), stringhe vuote vs null, padding di spazi
  • Dimensioni e limiti: campi molto lunghi, molte righe, chiavi ripetute, array profondamente nidificati

Non fermarti alla sintassi. Aggiungi anche fuzz semantico: scambia campi simili (email vs username), date estreme, ID duplicati, quantità negative o valori che violano enum.

Definisci cosa significa “passare” e conservalo

I fuzz test aiutano solo se i criteri di passaggio sono severi. Il tuo importer non dovrebbe mai crashare o bloccarsi, e gli errori dovrebbero essere coerenti e azionabili.

Un set pratico di regole di passaggio:

  • Nessun crash, timeout o picco di memoria oltre il limite
  • Errori chiari con puntatori a riga/campo (CSV) o path JSON
  • Codici errore stabili tra esecuzioni per lo stesso fallimento
  • Nessuna scrittura parziale a meno che il supporto non sia esplicito
  • Import riusciti producono risultati identici indipendentemente da formattazioni innocue (come spazi)

Esegui questi test in CI ad ogni modifica. Quando trovi un fallimento, salva il file esatto come fixture e aggiungi un test di regressione così non ritorna.

Se usi Claude Code per questo lavoro, fagli generare fixture seed che corrispondono al tuo contratto, un piano di mutazione e gli output di errore attesi. Tu scegli ancora le regole, ma ottieni rapidamente una superficie di test ampia, specialmente per quoting CSV e angoli JSON.

Trappole comuni che causano ticket ripetuti

La maggior parte dei ticket di import proviene da regole poco chiare e feedback inutili.

Una trappola comune è il parsing “best effort” non documentato. Se il tuo importer tronca spazi in modo silenzioso, accetta virgole e punto e virgola, o indovina formati di data, gli utenti costruiscono workflow intorno a queste supposizioni. Poi un piccolo cambiamento, o un generatore di file diverso, rompe tutto. Scegli il comportamento, documentalo e testalo.

Un altro problema ricorrente è il messaggio generico. “Invalid CSV” o “Bad request” costringe gli utenti a indovinare. Caricano lo stesso file cinque volte e il supporto alla fine chiede comunque il file. Gli errori dovrebbero puntare a riga, campo, una ragione chiara e un codice stabile.

Rigettare tutto il file per una riga sbagliata è spesso doloroso. A volte è corretto (es. import finanziari dove i dati parziali sono pericolosi). Molti import business possono proseguire e riportare un riepilogo, purché tu offra un'opzione esplicita come strict mode vs partial import.

I problemi di encoding di testo creano ticket ostinati. UTF-8 è il default giusto, ma i CSV reali spesso contengono BOM, virgolette tipografiche o spazi non separabili copiati dai fogli. Gestiscili in modo coerente e segnala cosa hai rilevato così l'utente può correggere le impostazioni di esportazione.

Infine, cambiare i codici errore tra release rompe client e automazioni. Migliora il wording se vuoi, ma mantieni i code e i significati stabili. Versionali solo quando è strettamente necessario.

Trappole da prevenire fin da subito:

  • Parsing “best effort” non documentato che cambia nel tempo
  • Errori senza puntatori a riga/campo e senza codice stabile
  • Import all-or-nothing senza opzione strict vs partial
  • UTF-8, BOM e caratteri invisibili gestiti in modo incoerente
  • Cambiamenti di code errore che rompono il handling client-side

Esempio: un cliente esporta un CSV da Excel, che aggiunge un BOM e formatta le date come 03/04/2026. Il tuo importer indovina MM/DD, ma il cliente si aspettava DD/MM. Se il tuo report di errore include il formato rilevato, il campo esatto e una correzione suggerita, l'utente può sistemarlo senza avanti e indietro.

Checklist rapida prima di rilasciare un importer

Change rules with confidence
Update validation safely with snapshots and rollback when rules change in production.

La maggior parte dei problemi di import sono piccoli disallineamenti tra cosa gli utenti pensano che il file significhi e cosa il tuo sistema accetta. Trattalo come una soglia di rilascio.

  • Headers e nomi dei campi: conferma che le colonne richieste siano presenti, i nomi corrispondono alle regole e i duplicati sono rifiutati. Decidi cosa fare con colonne extra (ignorare, avvisare, fallire) e mantieni coerenza.
  • Tipi di dato e formati: blocca come parsare interi vs decimali, booleani (true/false, 0/1, yes/no), date e timestamp (regole sui fusi). Preferisci un formato accettato per campo.
  • Null e valori mancanti: definisci cosa significa stringa vuota per ogni campo. Separa campo mancante, null esplicito e testo vuoto.
  • Limiti di sicurezza e dimensione: imposta limiti per dimensione file, righe massime e lunghezza massima dei campi. Fallisci presto con un messaggio chiaro.
  • Errori deterministici: lo stesso input errato dovrebbe produrre lo stesso code e la stessa forma del messaggio ogni volta.

Un test pratico: usa un file intenzionalmente disordinato. Esempio: un CSV dove l'header appare due volte (due colonne "email"), un campo booleano usa "Y" e una data è "03/04/05". Il tuo importer non dovrebbe indovinare. Dovrebbe o applicare una regola di mapping documentata o rifiutare con un errore specifico.

Due controlli che i team spesso saltano:

Primo, verifica che il tuo importer riporti errori con sufficiente dettaglio di posizione per correggere il file sorgente. “Invalid date” non è azionabile. “Riga 42, colonna start_date: expected YYYY-MM-DD, got 03/04/05” lo è.

Secondo, esegui lo stesso file invalido due volte e confronta i risultati. Se l'ordine degli errori cambia, i codici cambiano o i numeri di riga scivolano, gli utenti perdono fiducia. Il comportamento deterministico è noioso, ed è questo lo scopo.

Un esempio realistico e i passi successivi

Un import reale comune sono ordini clienti provenienti da un'esportazione di spreadsheet. Qualcuno esporta un CSV da un sistema vecchio, lo modifica in Excel e poi lo carica. La maggior parte dei ticket succede quando l'importer “sistema” i dati in modo silenzioso, o quando il messaggio di errore non dice cosa cambiare.

Immagina un file chiamato orders.csv con colonne: order_id,customer_email,order_date,currency,total_amount.

Ecco tre righe realisticamente sbagliate (come le vedrebbe l'utente):

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 riga 2 ha un'email non valida e una data ambigua. La riga 3 manca order_id, ha un codice valuta non supportato (US invece di USD) e un importo negativo.

Se la tua API restituisce errori, mantieni la forma coerente e specifica. Ecco un esempio di risposta che supporta il partial success:

{
  "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]
  }
}

Il partial success è importante perché gli utenti non dovrebbero dover ricaricare l'intero file. Un flusso di retry semplice è: correggi solo le righe fallite, esporta un piccolo CSV contenente le righe 2 e 3 e ricaricalo. Il tuo importer dovrebbe trattare questo come idempotente quando order_id è presente, così il “retry” aggiorna gli stessi record invece di crearne di duplicati.

Per il supporto, correlation_id è la via più veloce per la diagnosi. Un agente di supporto può chiedere quel valore singolo, trovare l'esecuzione di import nei log e confermare se il parser ha visto colonne extra, un delimitatore sbagliato o un encoding inatteso.

Passi successivi per rendere questo ripetibile:

  • Usa Claude Code per generare regole di validazione, righe di esempio errate e i codici/messaggi di errore che vuoi standardizzare.
  • Trasforma quegli esempi in test automatizzati (inclusi fuzz test) così i nuovi edge case diventano test che falliscono, non nuovi ticket.
  • Se costruisci con Koder.ai, usa la planning mode per redigere il contratto di import, generare il validator e i test, poi itera finché l'output degli errori rimane coerente tra CSV e JSON.

Domande frequenti

Why do CSV and JSON imports fail even when my importer code looks correct?

La maggior parte dei problemi deriva da dati reali disordinati, non da “codice sbagliato”. I problemi CSV riguardano in genere la forma (header, delimitatore, quoting, encoding), mentre i problemi JSON riguardano il più le informazioni (tipi, null vs vuoto, nidificazioni inattese). Tratta entrambi come input non attendibili e valida rispetto a un contratto esplicito.

Should my importer reject the whole file or allow partial success?

Definisci tre esiti in anticipo:

  • Accepted: tutto viene importato.
  • Rejected: niente viene importato perché il file non è affidabile (header errati, JSON non leggibile, encoding sbagliato).
  • Partially accepted: i record validi vengono importati; quelli non validi vengono scartati con motivazioni chiare.

Scegli un comportamento predefinito (molti prodotti optano per partial) e mantienilo coerente in UI e API.

What should an “import contract” include?

Scrivi un import contract prima di implementare la validazione:

  • Formati accettati (delimitatore CSV, header obbligatorio, gestione UTF-8/BOM; JSON array vs object vs JSON Lines)
  • Regole dei campi (obbligatorio/opzionale/default)
  • Normalizzazione (trim, regole di case, formati di data)
  • Definizione e gestione dei duplicati
  • Dove avviene la validazione (client, server o entrambi)

Questo evita sorprese del tipo “funzionava ieri” quando il comportamento cambia.

How do I handle weird dates and type drift ("00123" → 123, yes/no booleans)?

Preferisci un formato univoco per campo (ad esempio date come YYYY-MM-DD). Se accetti varianti, specifica esplicitamente quali (ad esempio accetta true/false/1/0, ma non tutte le congetture prodotte dai fogli di calcolo). Evita di indovinare date ambigue come 01/02/03; richiedi il formato ISO o rigetta con un errore chiaro.

What’s the best way to deal with duplicates during import?

Decidi:

  • Cosa conta come duplicato (email, external_id o una chiave composta)
  • Ambito della rilevazione (nel file, contro i dati esistenti o entrambi)
  • Azione da intraprendere (keep first, keep last, merge o reject)

Se gli utenti possono ritentare import, combina questa logica con l'idempotenza così lo stesso upload non crea duplicati.

How should I structure validation rules so they stay readable and testable?

Usa livelli invece di un unico grande validate():

  • Normalize l'input in una forma canonica
  • Regole a livello di campo (tipo, range, enum)
  • Regole cross-field (start < end, totale = sottototale + tasse - sconto)
  • Regole a livello di file (header obbligatori, chiavi duplicate, versione supportata)

Le regole piccole e nominate sono più facili da testare e modificare.

What should my error reporting format look like?

Restituisci una forma stabile di errore con:

  • code (identificatore stabile)
  • message (leggibile dall'utente)
  • path/field (nome colonna o JSON pointer)
  • row/line (per CSV)
  • severity (error vs warning)

Rendilo azionabile includendo l'aspettativa e il valore effettivo quando possibile.

What should my import API return on success and on failure?

Restituisci sempre un riepilogo coerente, anche quando ci sono errori:

  • conteggi: created, updated, skipped, failed, più totalRows/totalRecords
  • status (success, rejected, completed_with_errors)
  • timestamp (startedAt, finishedAt)
  • un correlationId per support/debug

Per file grandi, includi un piccolo errorsSample e un modo per recuperare il report completo in seguito.

How do I make imports idempotent so retries don’t create duplicates?

Supporta i retry esplicitamente:

  • Accetta un idempotencyKey (o usa l'hash del file)
  • Restituisci l'importId esistente se la richiesta è ripetuta
  • Definisci le regole di matching per upsert (ad esempio, email è la chiave unica)

Senza questo, i retry degli utenti possono creare record duplicati.

How do I fuzz test CSV/JSON imports without making the test suite unmanageable?

Inizia con pochi file seed buoni, poi genera molte mutate piccole (una modifica alla volta):

  • encoding (UTF-8 BOM, byte non validi)
  • struttura (header mancanti, colonne extra, delimitatore sbagliato)
  • quoting/newlines (virgolette non chiuse, newline incorporati)
  • edge di tipo (numeri enormi, empty vs null, NaN/Infinity in JSON)
  • limiti di dimensione (campi lunghi, nidificazioni profonde)

Un test di fuzz “passa” quando l'importer non va in crash/hang e restituisce errori deterministici e utilizzabili.

Related posts