Claude Code dla poprawności importu/eksportu danych — praktyczne kroki
Claude Code dla poprawności importu/eksportu danych: zdefiniuj reguły walidacji, spójne formaty błędów i fuzz testy dla importów CSV/JSON, by zredukować trudne tickety wsparcia.

Co idzie nie tak przy importach CSV i JSON
Importy rzadko zawodzą dlatego, że kod jest „zły”. Zawodzą, bo dane z życia są brudne, niespójne i wygenerowane przez osoby, które nie znały twoich założeń.
Problemy z CSV dotyczą zwykle kształtu i formatowania. Problemy z JSON dotyczą raczej znaczenia i typów. Oba formaty mogą psuć się w sposób wyglądający na drobny, a dający mylące efekty.
Te problemy pojawiają się w zgłoszeniach do supportu raz po raz:
- Brakujące wymagane pola (email, id, country) lub kolumny zmienione przez kogoś „porządkującego” plik
- Dziwne daty (01/02/03, 2024-13-01, liczbowe numery Excela, mieszane strefy czasowe)
- Dodatkowe kolumny lub niespodziewane zagnieżdżone obiekty JSON dodane przez inne narzędzie
- Dryf typów ("00123" → 123, true/false → "yes"/"no")
- Duplikaty i niemal-duplikaty (to samo id dwukrotnie, ta sama osoba z inną wielkością liter)
Poprawność to nie tylko „czy się zaimportowało”. Musisz zdecydować, które rezultaty są dozwolone, bo użytkownicy zauważą ciche błędy częściej niż głośne awarie.
Większość zespołów potrafi zgodzić się na trzy wyniki:
- Accepted: wszystkie wiersze lub rekordy są poprawne i zaimportowane
- Rejected: nic nie jest importowane, bo plik nie budzi zaufania (złe nagłówki, złe kodowanie, nieczytelny JSON)
- Partially accepted: poprawne rekordy są importowane, niepoprawne są pomijane z jasnymi powodami
Edge case’y zamieniają się w przeróbki, gdy ludzie nie wiedzą, co poszło nie tak i jak to szybko naprawić. Typowy scenariusz: klient przesyła CSV z 5000 wierszy, importer zwraca „Invalid format”, i robi trzy losowe próby naprawy. To sprowadza się do wielu ticketów i kogoś po twojej stronie próbującego odtworzyć plik lokalnie.
Ustal cele redukujące cykl: mniej powtórek, szybsze naprawy, przewidywalne rezultaty. Zanim napiszesz reguły, zdecyduj, co oznacza „partial” (i czy je dopuszczasz), jak zgłaszać problemy na poziomie wiersza i co użytkownik powinien zrobić dalej (edytować plik, mapować pola, czy wyeksportować poprawioną wersję). Jeśli używasz platformy wspomagającej, takiej jak Koder.ai (koder.ai), żeby szybko generować walidatory i testy, kontrakt importu i tak utrzyma spójność zachowania w miarę rozwoju produktu.
Zdecyduj o kontrakcie importu zanim napiszesz reguły
Zanim napiszesz pojedynczą regułę walidacyjną, ustal, co oznacza „prawidłowe wejście” dla twojego produktu. Większość błędów importu to niezgodność oczekiwań między tym, co użytkownik przesyła, a tym, co system zakłada w sposób ukryty.
Zacznij od formatów i bądź jednoznaczny. „CSV” może znaczyć przecinek lub średnik, wiersz nagłówka albo nie, UTF-8 albo „co wygenerował Excel”. Dla JSON zdecyduj, czy akceptujesz pojedynczy obiekt, tablicę rekordów, czy JSON Lines (jeden obiekt JSON na linię). Jeśli akceptujesz zagnieżdżony JSON, zdefiniuj, które ścieżki odczytujesz, a które ignorujesz.
Następnie zablokuj kontrakt pól. Dla każdego pola zdecyduj, czy jest wymagane, opcjonalne, czy opcjonalne z wartością domyślną. Wartości domyślne są częścią kontraktu, a nie szczegółem implementacyjnym. Jeśli country brakuje, czy domyślnie zapisujesz puste, wybierasz konkretny kraj, czy odrzucasz wiersz?
Zachowanie parsera to miejsce, gdzie „tolerancyjne” importy tworzą długoterminowe problemy. Zdecyduj z góry, jak rygorystyczni jesteście w kwestii obcinania spacji, normalizacji wielkości liter i akceptowania wariantów jak "yes"/"true"/"1". Tolerancja jest w porządku, jeśli jest przewidywalna i udokumentowana.
Duplikaty to kolejna decyzja kontraktowa wpływająca na poprawność i zaufanie. Zdefiniuj, co liczy się jako duplikat (ten sam email, ten sam external_id, ta sama kombinacja pól), gdzie wykrywasz duplikaty (w pliku, w stosunku do istniejących danych, albo obie) i co robisz, gdy wystąpią (zachowaj pierwszy, zachowaj ostatni, scal, albo odrzuć).
Lista kontrolna kontraktu, którą możesz wkleić do specyfikacji:
- Akceptowane formaty i kodowanie (separator CSV, JSON vs JSON Lines, obsługa zagnieżdżeń)
- Reguły pól (wymagane/opcjonalne/wartości domyślne, dozwolone wartości)
- Reguły normalizacji (trim, wielkość liter, formaty dat/liczb)
- Definicja i obsługa duplikatów (zakres detekcji, wybrane zachowanie)
- Miejsce walidacji (klient, serwer, lub oba)
Przykład: import „customers”. Jeśli email jest kluczem unikalnym, zdecyduj, czy " [email protected] " równa się "[email protected]", czy brak email jest akceptowany, jeśli istnieje external_id, oraz czy duplikaty wewnątrz pliku mają być odrzucone nawet gdy baza nie ma zgodności. Kiedy kontrakt jest ustalony, spójne zachowanie w UI i API jest dużo łatwiejsze, niezależnie od tego, czy implementujesz to w Koder.ai czy gdzie indziej.
Reguły walidacji, które pozostają czytelne i testowalne
Bałagan przy importach często zaczyna się od jednej gigantycznej funkcji validate(). Czystsze podejście to warstwowe reguły z jasnymi nazwami i małymi funkcjami. To ułatwia przegląd zmian i pisanie testów.
Zacznij od reguł na poziomie pola: sprawdzeń, które pojedyncza wartość może zdać lub oblać samodzielnie (typ, zakres, długość, dozwolone wartości, regex). Trzymaj je nudnymi i przewidywalnymi. Przykłady: email pasuje do podstawowego wzorca email, age jest liczbą całkowitą między 0 a 120, status należy do active|paused|deleted.
Dodawaj reguły międzypolowe tylko tam, gdzie mają znaczenie. Te sprawdzenia zależą od wielu pól i tam kryją się błędy. Klasyczne przykłady: startDate musi być przed endDate, albo total równa się subtotal + tax - discount. Pisz te reguły tak, by wskazywały konkretne pola, a nie tylko „rekord nieprawidłowy”.
Oddziel reguły na poziomie rekordu od reguł na poziomie pliku. Reguła rekordowa sprawdza jeden wiersz (CSV) lub jeden obiekt (JSON). Reguła plikowa sprawdza całe przesłanie: czy wymagane nagłówki istnieją, czy klucz unikalny się nie powtarza, czy liczba kolumn odpowiada oczekiwaniom, lub czy plik deklaruje obsługiwaną wersję.
Normalizacja powinna być jawna, a nie „magiczna”. Zdecyduj, co normalizujesz przed walidacją i udokumentuj to. Typowe przykłady: obcinanie spacji, normalizacja Unicode (by wizualnie identyczne znaki porównywały się tak samo) oraz formatowanie numerów telefonów do jednego spójnego formatu przechowywania.
Struktura, która pozostaje czytelna:
- Normalize: przekształć surowe wejście do kanonicznego kształtu.
- Validate fields: małe, wielokrotnego użytku sprawdzenia na pole.
- Validate relationships: sprawdzenia między polami z jasnym wskazaniem docelowych pól.
- Validate file rules: nagłówki, duplikaty i obsługa wersji.
- Test each layer: testy jednostkowe dla każdej reguły oraz kilka end-to-endowych fixture'ów.
Wersjonuj swoje reguły. Dodaj schemaVersion (lub profil importu) w pliku lub żądaniu API. Gdy zmienisz, co oznacza „prawidłowe”, nadal będziesz mógł ponownie zaimportować starsze eksperty używając starej wersji. To jedna decyzja, która zapobiega wielu ticketom „wczoraj działało".
Zaprojektuj format raportowania błędów, na który można zareagować
Dobry importer kończy się w pomocny sposób. Niejasne błędy prowadzą do losowych prób i niepotrzebnej pracy supportu. Jasny format błędów pomaga użytkownikom szybko naprawić plik i pomaga wam poprawiać walidację bez łamania klientów.
Zacznij od stabilnego kształtu obiektu błędu i trzymaj go spójnie dla CSV i JSON. Możesz użyć Claude Code do zaproponowania schematu i kilku realistycznych przykładów, a potem zamrozić go jako część kontraktu importu.
Stabilny obiekt błędu
Traktuj każdy błąd jako mały rekord z polami, które się nie zmieniają. Treść komunikatu może ewoluować, ale code i path powinny być trwałe.
code: krótki, stabilny identyfikator, np.REQUIRED_MISSINGalboINVALID_DATEmessage: przyjazne zdanie dla UIpath: gdzie jest problem (JSON pointer jak/customer/email, albo nazwa kolumny jakemail)rowlubline: dla CSV podaj numer wiersza zaczynając od 1 (opcjonalnie oryginalny wiersz)severity: przynajmniejerroriwarning
Uczyń błędy działającymi. Dołącz, co oczekiwano i co faktycznie było widziane, a jeśli możliwe, pokaż przykład, który by przeszedł. Na przykład: oczekiwano YYYY-MM-DD, otrzymano 03/12/24.
Grupowanie dla UI i debugowania
Nawet jeśli zwracasz płaską listę, dołącz wystarczająco danych, by pogrupować błędy po wierszu i po polu. Wiele interfejsów chce pokazać „Wiersz 12 ma 3 problemy” i podświetlić kolumny. Zespoły wsparcia lubią grupowanie, bo wzorce stają się oczywiste (np. każdy wiersz brakuje country).
Kompaktowa odpowiedź może wyglądać tak:
{
"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"
}
]
}
Zaplanuj lokalizację bez zmiany kodów błędów. Traktuj code jako neutralny językowo i trwały, a message jako pole nadpisywalne. Jeśli później dodasz messageKey lub przetłumaczone komunikaty, starzy klienci nadal mogą polegać na tych samych kodach do filtrowania i analiz.
Co API importu powinno zwracać przy sukcesie i przy błędzie
Aby uniknąć „tajemniczych importów”, odpowiedź API powinna odpowiedzieć na dwa pytania: co się stało i co użytkownik powinien zrobić dalej.
Zwracaj jasne podsumowanie importu (za każdym razem)
Nawet przy błędach zwracaj spójne podsumowanie, aby UI i narzędzia wsparcia mogły obsłużyć każde przesłanie w ten sam sposób.
Uwzględnij:
created,updated,skipped,failed(liczniki)totalRows(lubtotalRecordsdla JSON)mode(np. "createOnly", "upsert" lub "updateOnly")startedAtifinishedAt(znaczniki czasu)correlationId, o który support może zapytać
Ten correlationId jest tego wart. Gdy ktoś zgłasza „nie zaimportowało się”, znajdziesz dokładny przebieg i raport błędów bez zgadywania.
Dołącz użyteczne błędy oraz sposób pobrania pełnego raportu
Nie wrzucaj 10 000 błędów w odpowiedzi. Zwróć małą próbkę (np. 20), która pokazuje wzorzec, i zapewnij osobny sposób na pobranie pełnego raportu w razie potrzeby.
Każdy błąd powinien być specyficzny i stabilny:
- lokalizacja: numer wiersza (CSV) lub ścieżka podobna do JSON pointer (JSON)
- nazwa pola
- kod błędu (do czytania maszynowego)
- komunikat (dla człowieka)
- odrzucona wartość (uważaj na dane wrażliwe)
Przykładowy kształt odpowiedzi (sukces z błędami w wierszach):
{
"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"
}
}
Zwróć uwagę na pole next. Nawet minimalny payload sukcesu powinien pomóc produktowi ruszyć dalej: pokaż ekran przeglądu, zaoferuj retry, albo otwórz zaimportowaną kolekcję.
Zdefiniuj idempotencję, żeby powtórne przesłania nie tworzyły powtórzeń
Ludzie powtarzają. Sieci padają. Jeśli ten sam plik zostanie zaimportowany dwukrotnie, chcesz przewidywalnych rezultatów.
Bądź jawny co do idempotencji: akceptuj idempotencyKey (lub oblicz hash pliku) i zwróć istniejące importId, jeśli żądanie jest powtórzeniem. Jeśli tryb to upsert, zdefiniuj regułę dopasowania (np. „email jest kluczem unikalnym”). Jeśli to create-only, zwracaj „skipped” dla duplikatów, a nie „created again”.
Używaj odpowiedniego statusu dla porażek, ale trzymaj kształt odpowiedzi stabilny
Jeśli całe żądanie jest nieprawidłowe (zły auth, nieobsługiwany content type, nieczytelny plik), szybko odrzuć i zwróć status: "rejected" z krótką listą błędów. Jeśli plik jest czytelny, ale ma problemy na poziomie wierszy, traktuj go jako ukończone zadanie z failed > 0, żeby użytkownicy mogli poprawić i ponownie przesłać bez utraty podsumowania.
Jak użyć Claude Code do generowania reguł i przykładów
Użyteczny nawyk: każ delegatowi modelu napisanie kontraktu w ustrukturyzowanym formacie, a nie w akapitach. „Pomocne paragrafy” często pomijają szczegóły jak reguły trimowania, wartości domyślne i czy pusty cell znaczy "missing" czy "empty".
Użyj promptu, który wymusi tabelę, którą człowiek szybko sprawdzi, a deweloper przekształci w kod. Poproś o każdej regule: przykłady pass i fail oraz wyraźną notatkę o niejednoznacznościach (np. pusty 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).
Po pierwszym szkicu, doprecyzuj prosząc o po jednym pozytywnym i jednym negatywnym przykładzie na regułę. To wymusza pokrycie trudnych narożników jak puste stringi, wartości z samymi spacjami, brakujące kolumny, null vs "null", bardzo duże liczby, notacja naukowa, duplikaty ID i dodatkowe pola JSON.
Dla konkretnego scenariusza: import „customers” z CSV: email jest wymagany, phone opcjonalny, a signup_date domyślnie dziś, jeśli brak. Model powinien wykryć sprzeczność, jeśli też powiesz, że signup_date jest wymagany. Powinien zaproponować testy typu import_customers_missing_email_returns_row_error i określić kod błędu oraz kształt wiadomości.
Zrób jeszcze jedno przejście przed implementacją: poproś model, aby wypunktował reguły jako checklistę i wskazał miejsca, gdzie wartości domyślne, pola wymagane i normalizacja mogą kolidować. Ten krok przeglądu łapie wiele zachowań, które później generują tickety.
Krok po kroku: fuzz testy dla importów CSV i JSON
Fuzz testing powstrzymuje „dziwne pliki” przed staniem się zgłoszeniami do supportu. Zacznij od małego zestawu poprawnych plików, potem wygeneruj tysiące lekko uszkodzonych wariantów i upewnij się, że importer reaguje bezpiecznie i jasno.
Zbuduj zbiór bazowy, potem mutuj
Zacznij od małego zestawu przykładów reprezentujących realne użycie: najmniejszy prawidłowy plik, typowy plik i duży plik. Dla JSON uwzględnij jeden obiekt, wiele obiektów i zagnieżdżenia, jeśli je wspierasz.
Następnie dodaj automatyczny mutator, który zmienia jedną rzecz naraz. Zachowaj reprodukowalność przez logowanie ziarna losowości, aby można było odtworzyć błędy.
Wymiary fuzzingu, które łapią większość realnych problemów:
- Problemy z kodowaniem: UTF-8 z BOM, nieprawidłowe sekwencje bajtów, mieszana normalizacja
- Problemy strukturalne: brak nagłówków, dodatkowe kolumny/pola, zły separator, przecinki końcowe
- Cytowanie i nowe wiersze: niezamknięte cudzysłowy, wbudowane nowe linie, CRLF vs LF, niespójne escape'owanie
- Krawędzie typów: ogromne liczby całkowite, NaN/Infinity (JSON), puste stringi vs null, padding spacjami
- Rozmiar i limity: bardzo długie pola, dużo wierszy, powtarzające się klucze, głęboko zagnieżdżone tablice
Nie zatrzymuj się na składni. Dodaj fuzz semantyczny: zamieniaj pokrewne pola (email vs username), ekstremalne daty, duplikaty ID, ujemne ilości lub wartości łamiące enumy.
Zdefiniuj, co znaczy „pass”, potem to zamroź
Fuzz testy pomagają tylko, jeśli kryteria przejścia są ścisłe. Twój importer nigdy nie powinien padać lub wieszać się, a błędy powinny być spójne i działające.
Praktyczny zestaw kryteriów pass:
- Brak crashy, timeoutów ani skoków pamięci poza ustalony limit
- Czytelne błędy z wskaźnikami wiersz/pole (CSV) lub ścieżkami JSON
- Stabilne kody błędów dla tych samych awarii
- Brak częściowych zapisów, chyba że explicite wspierasz częściowy sukces
- Sukcesy importu dają identyczne wyniki niezależnie od nieszkodliwych formatowań (np. spacje)
Uruchamiaj te testy w CI przy każdej zmianie. Gdy znajdziesz awarię, zachowaj dokładny plik jako fixture i dodaj test regresyjny, żeby to się nie powtórzyło.
Jeśli używasz Claude Code do tej pracy, poproś go o wygenerowanie seed fixtures zgodnych z twoim kontraktem, plan mutacji i oczekiwane wyjścia błędów. Nadal to ty decydujesz o regułach, ale zyskujesz szeroką powierzchnię testową szybko, zwłaszcza dla cytowania w CSV i narożników JSON.
Typowe pułapki powodujące powtarzające się tickety
Najwięcej zgłoszeń importu pochodzi z niejasnych reguł i nieużytecznego feedbacku.
Jedna pułapka to „best effort” parsowanie bez dokumentacji. Jeśli importer cicho obcina spacje, akceptuje przecinki i średniki, albo zgaduje formaty dat, użytkownicy budują workflowy wokół tych zgadywań. Mała zmiana lub inny generator plików psuje wszystko. Wybierz zachowanie, udokumentuj i przetestuj.
Kolejny powtarzający się problem to generyczny komunikat o błędzie. „Invalid CSV” czy „Bad request” zmusza użytkownika do zgadywania — wysyła ten sam plik pięć razy, a support i tak prosi o plik. Błędy powinny wskazywać wiersz, pole, jasny powód i stabilny kod.
Odrzucanie całego pliku za jeden zły wiersz też bywa bolesne. Czasem to konieczne (np. importy finansowe), ale wiele biznesowych importów może kontynuować i raportować podsumowanie, pod warunkiem że oferujesz opcję strict mode vs partial import.
Problemy z kodowaniem tekstu generują uporczywe tickety. UTF-8 to dobry domyślny wybór, ale realne CSV zawierają BOM, zawinięte cudzysłowy lub niełamliwe spacje z arkuszy. Obsługuj to konsekwentnie i raportuj, co wykryto, aby użytkownik mógł poprawić ustawienia eksportu.
Na koniec: zmiana kodów błędów między wersjami łamie klientów i automatyzacje. Poprawiaj treść komunikatów, jeśli chcesz, ale zachowuj kody i znaczenia. Wersjonuj tylko wtedy, gdy naprawdę trzeba.
Warto zabezpieczyć się przed:
- Niedokumentowanym „best effort” parsowaniem, które zmienia się w czasie
- Błędami bez wskaźników wiersz/pole i bez stabilnych kodów błędów
- Podejściem wszystko albo nic bez opcji strict vs partial
- Nieobsługiwaniem BOM i innych niewidocznych znaków kopiowanych z arkuszy
- Zmianami kodów błędów, które łamią klienty
Przykład: klient eksportuje CSV z Excela, który dodaje BOM i formatuje daty jako 03/04/2026. Twój importer zgaduje MM/DD, ale klient miał DD/MM. Jeśli raport błędu zawiera wykryty format, dokładne pole i proponowaną poprawkę, użytkownik skoryguje eksport bez długiego back-and-forth.
Szybka lista kontrolna przed wypuszczeniem importera
Większość problemów importu to małe niezgodności między tym, co użytkownik myśli, że plik oznacza, a tym, co system akceptuje. Traktuj to jako bramkę wydania.
- Nagłówki i nazwy pól: potwierdź, że wymagane kolumny są obecne, nazwy pasują do reguł i duplikaty są odrzucane. Zdecyduj, co robić z dodatkowymi kolumnami (ignoruj, ostrzegaj, odrzuć) i trzymaj to spójnie.
- Typy danych i formaty: ustal jak parsujesz integer vs decimal, booleany (true/false, 0/1, yes/no), daty i znaczniki czasu (reguły strefy czasowej). Preferuj jeden format na pole.
- Null i brak wartości: zdefiniuj, co znaczy pusty string dla każdego pola. Rozdziel brak pola, explicit null i pusty tekst.
- Limity i bezpieczeństwo: ustaw limity rozmiaru pliku, maksymalną liczbę wierszy i maksymalną długość pola. Odrzuć wcześniej z jasnym komunikatem.
- Deterministyczne błędy: to samo złe wejście powinno zawsze dawać ten sam kod błędu i kształt wiadomości.
Praktyczny test: użyj jednego celowo zabałaganionego pliku. Przykład: CSV z podwójnym nagłówkiem (dwa „email”), pole boolean jako „Y” i data „03/04/05”. Twój importer nie powinien zgadywać — albo zastosuj udokumentowane mapowanie, albo odrzuć z konkretnym błędem.
Dwa sprawdzenia, które zespoły często pomijają:
Po pierwsze, upewnij się, że importer raportuje błędy z wystarczającymi informacjami lokalizacyjnymi, by naprawić źródłowy plik. „Invalid date” to za mało. „Wiersz 42, kolumna start_date: oczekiwano YYYY-MM-DD, otrzymano 03/04/05” to jest.
Po drugie, uruchom ten sam nieprawidłowy plik dwa razy i porównaj wyniki. Jeśli kolejność błędów się zmienia, kody się zmieniają lub numery wierszy przesuwają, użytkownicy tracą zaufanie. Deterministyczne zachowanie jest nudne — i to jest jego zaleta.
Realistyczny scenariusz i kolejne kroki
Częstym realnym importem są zamówienia klientów z eksportu arkusza. Ktoś eksportuje CSV ze starego systemu, edytuje w Excelu, potem wrzuca. Większość ticketów powstaje, gdy importer cicho „poprawia” dane albo gdy komunikat błędu nie mówi, co zmienić.
Wyobraź sobie plik orders.csv z kolumnami: order_id,customer_email,order_date,currency,total_amount.
Oto trzy realistyczne złe wiersze (tak jak widziałby je użytkownik):
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
Wiersz 2 ma niepoprawny email i niejednoznaczny format daty. Wiersz 3 brakuje order_id, ma nieobsługiwany kod waluty (US zamiast USD) i ujemną kwotę.
Jeśli twoje API zwraca błędy, trzymaj kształt spójny i konkretny. Przykładowa odpowiedź wspierająca częściowy sukces:
{
"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]
}
}
Częściowy sukces ma znaczenie, bo użytkownik nie powinien przesyłać całego pliku ponownie. Prosty flow retry: napraw tylko nieudane wiersze, wyeksportuj mały CSV zawierający wiersze 2 i 3 i prześlij ponownie. Twój importer powinien traktować to jako idempotentne, gdy order_id istnieje, więc retry zaktualizuje te same rekordy zamiast tworzyć duplikaty.
Dla wsparcia, correlation_id to najszybsza ścieżka diagnozy. Agent supportu prosi tylko o tę wartość, znajduje przebieg importu w logach i potwierdza, czy parser zobaczył dodatkowe kolumny, zły separator czy nieoczekiwane kodowanie.
Kolejne kroki, które uczynią to powtarzalnym:
- Użyj Claude Code do wygenerowania reguł walidacji, przykładowych złych wierszy i kodów/komunikatów, które chcesz ustandaryzować.
- Zamień te przykłady w testy automatyczne (w tym fuzz tests), aby nowe narożniki stały się testami końcowymi, a nie nowymi ticketami.
- Jeśli budujesz z Koder.ai, użyj planning mode do opracowania kontraktu importu, wygenerowania validatora i testów, a potem iteruj, aż wyjście błędów pozostanie spójne dla CSV i JSON.
Często zadawane pytania
Why do CSV and JSON imports fail even when my importer code looks correct?
Większość awarii wynika z bałaganu w danych, a nie z „złego kodu”. Problemy z CSV zwykle dotyczą kształtu danych (nagłówki, separator, cytowanie, kodowanie), natomiast w JSON chodzi częściej o znaczenie (typy, null kontra pusty tekst, niespodziewane zagnieżdżenia). Traktuj oba formaty jako niezaufane wejście i waliduj je względem jasnego kontraktu.
Should my importer reject the whole file or allow partial success?
Zdefiniuj trzy wyniki z góry:
- Accepted: wszystko zostaje zaimportowane.
- Rejected: nic nie jest importowane, plik jest niegodny zaufania (złe nagłówki, nieczytelny JSON, złe kodowanie).
- Partially accepted: poprawne rekordy są importowane; niepoprawne są pomijane z jasnymi powodami.
Wybierz domyślne zachowanie (wiele produktów wybiera partial) i trzymaj się go konsekwentnie w UI i API.
What should an “import contract” include?
Spisz import contract przed zaczęciem walidacji:
- Akceptowane formaty (separator CSV, wymagany nagłówek, obsługa UTF-8/BOM; JSON: tablica vs obiekt vs JSON Lines)
- Zasady pól (wymagane/opcjonalne/wartości domyślne)
- Normalizacja (trim, reguły wielkości liter, formaty dat)
- Definicja i obsługa duplikatów
- Miejsce walidacji (klient, serwer lub oba)
To zapobiega sytuacjom „wczoraj działało”, a dziś nie.
How do I handle weird dates and type drift ("00123" → 123, yes/no booleans)?
Wybierz jeden, niejednoznaczny format na pole (np. daty jako YYYY-MM-DD). Jeśli akceptujesz warianty, zrób to jawnie i przewidywalnie (np. przyjmuj true/false/1/0, ale nie wszystkie zgadywane formaty arkuszy). Unikaj zgadywania dwuznacznych dat typu 01/02/03; wymagaj ISO lub odrzuć z czytelnym błędem.
What’s the best way to deal with duplicates during import?
Zdecyduj:
- Co uznajesz za duplikat (email, external_id, lub klucz złożony)
- Zakres wykrywania (w pliku, wobec istniejących rekordów, lub oba)
- Działanie (zachowaj pierwszy, zachowaj ostatni, scal, odrzuć)
Jeśli użytkownicy mogą ponawiać importy, połącz to z idempotencją, żeby to samo przesłanie nie tworzyło duplikatów.
How should I structure validation rules so they stay readable and testable?
Zamiast jednego gigantycznego validate(), zastosuj warstwy:
- Normalize: przekształć surowe wejście do kanonicznego kształtu
- Field-level rules: drobne, powtarzalne sprawdzenia (typ, zakres, enum)
- Cross-field rules: walidacje zależne od wielu pól
- File-level rules: nagłówki, duplikaty, wersja pliku
Małe, nazwane reguły są łatwiejsze w testowaniu i bezpieczniejsze przy zmianach.
What should my error reporting format look like?
Zwracaj stabilny kształt błędu z polami:
code(stabilny identyfikator)message(czytelny dla użytkownika)path/field(nazwa kolumny lub JSON pointer)row/line(dla CSV)severity(errorvswarning)
Uczyń go działającym: podaj, czego oczekiwano i co faktycznie otrzymano, kiedy to możliwe.
What should my import API return on success and on failure?
Zawsze zwracaj spójne podsumowanie, nawet przy błędach:
- liczniki:
created,updated,skipped,failed, plustotalRows/totalRecords status(success, rejected, completed_with_errors)- znaczniki czasu (
startedAt,finishedAt) correlationIddla wsparcia i debugowania
Dla dużych plików zwróć próbkę błędów (errorsSample) i sposób na pobranie pełnego raportu.
How do I make imports idempotent so retries don’t create duplicates?
Wspieraj ponawianie explicite:
- Akceptuj
idempotencyKey(lub użyj hasha pliku) - Zwróć istniejące
importId, jeśli żądanie jest powtórzeniem - Zdefiniuj reguły dopasowania przy upsercie (np. email jako klucz unikalny)
Bez tego zwykłe ponowienia mogą tworzyć duplikaty.
How do I fuzz test CSV/JSON imports without making the test suite unmanageable?
Zacznij od kilku prawidłowych plików-wzorów, potem generuj małe, pojedyncze mutacje:
- kodowanie (UTF-8 BOM, nieprawidłowe bajty)
- struktura (brak nagłówków, dodatkowe kolumny, zły separator)
- cytowanie/nowe wiersze (niezamknięte cudzysłowy, CRLF vs LF)
- krawędzie typów (ogromne liczby, pusty vs null,
NaN/Infinityw JSON) - limity rozmiaru (długie pola, głębokie zagnieżdżenia)
Test „przechodzi”, jeśli importer nie pada, nie wiesza się i zwraca deterministyczne, użyteczne błędy. Uruchamiaj te testy w CI i dodawaj regresje dla znalezionych przypadków.
What are common traps that cause repeated support tickets?
Najczęściej zgłaszane problemy wynikają z niejasnych reguł i nieużytecznych komunikatów błędów.
Kilka powtarzających się pułapek:
- „Best effort” parsowanie, które nie jest udokumentowane i zmienia się w czasie
- generyczne błędy typu „Invalid CSV” bez wskazania wiersza/pola
- podejście wszystko albo nic bez opcji strict vs partial
- nieobsłużone znaki BOM i inne niewidoczne znaki z arkuszy
- zmiana kodów błędów między wydaniami
Jeśli importer zgaduje format dat z „03/04/2026”, ale użytkownik miał na myśli DD/MM, raport z wykrytym formatem i proponowaną poprawką oszczędza wiele ticketów.
What’s a quick checklist before shipping an importer?
Przed wypuszczeniem traktuj importer jako bramkę wydania. Szybkie checklisty:
- Nagłówki i nazwy pól: wymagane kolumny obecne, duplikaty nagłówków odrzucone; co robimy z dodatkowymi kolumnami (ignoruj, ostrzegaj, odrzuć).
- Typy danych i formaty: ustal jeden format dla pól (liczby, daty, booleany) i testuj go.
- Null i brak wartości: rozróżnij brak pola, explicit null i pusty tekst.
- Limity i bezpieczeństwo: maksymalny rozmiar pliku, maksymalna liczba wierszy, maksymalna długość pola.
- Deterministyczne błędy: to samo złe wejście powinno zwracać ten sam kod błędu i ten sam kształt wiadomości.
Przykładowy test: celowo zabałaganiony plik (podwójny nagłówek, boolean jako Y, data 03/04/05) — importer nie powinien zgadywać i powinien albo zastosować udokumentowane mapowanie, albo odrzucić z konkretnym błędem.