7 menit

Claude Code untuk ketepatan impor/ekspor data: langkah praktis

Claude Code untuk ketepatan impor/ekspor data: tentukan aturan validasi, format error konsisten, dan fuzz tests untuk impor CSV/JSON agar mengurangi tiket dukungan kasus tepi.

Claude Code untuk ketepatan impor/ekspor data: langkah praktis

Apa yang sering salah dengan impor CSV dan JSON

Impor jarang gagal karena kode itu “salah”. Mereka gagal karena data dunia nyata berantakan, tidak konsisten, dan dibuat oleh orang yang tidak melihat asumsi Anda.

Masalah CSV biasanya tentang bentuk dan format. Masalah JSON biasanya tentang makna dan tipe. Keduanya bisa rusak dengan cara yang tampak kecil tapi menghasilkan hasil yang membingungkan.

Masalah ini muncul berulang kali di tiket dukungan:

  • Field yang wajib hilang (email, id, country) atau kolom yang diganti nama oleh seseorang yang “membersihkan” file
  • Tanggal aneh (01/02/03, 2024-13-01, nomor serial Excel, zona waktu campuran)
  • Kolom ekstra atau objek JSON bertingkat tak terduga yang ditambahkan oleh tool lain
  • Drift tipe ("00123" menjadi 123, true/false menjadi "yes"/"no")
  • Duplikat dan hampir-duplikat (id yang sama dua kali, atau orang yang sama dengan huruf besar/kecil berbeda)

Ketepatan bukan hanya “apakah terimpor”. Anda harus memutuskan hasil mana yang diterima, karena pengguna lebih memperhatikan kesalahan diam daripada kegagalan keras.

Kebanyakan tim bisa setuju pada tiga hasil:

  • Accepted: semua baris atau record valid dan diimpor
  • Rejected: tidak ada yang diimpor karena file tidak dapat dipercaya (header salah, encoding buruk, JSON tak terbaca)
  • Partially accepted: record valid diimpor, yang tidak valid dilewati dengan alasan yang jelas

Edge case menjadi rework ketika orang tidak bisa tahu apa yang salah atau bagaimana memperbaikinya dengan cepat. Skenario umum: pelanggan mengunggah CSV berisi 5.000 baris, importer mengatakan “Invalid format”, dan mereka mencoba lagi tiga kali dengan edit acak. Itu menjadi banyak tiket plus seseorang di tim Anda mencoba mereproduksi file secara lokal.

Tetapkan tujuan yang mengurangi siklus: lebih sedikit retry, perbaikan lebih cepat, hasil yang dapat diprediksi. Sebelum menulis aturan, putuskan apa arti “partial” (dan apakah Anda mengizinkannya), bagaimana Anda akan melaporkan masalah per baris, dan apa yang harus dilakukan pengguna selanjutnya (mengedit file, memetakan field, atau mengekspor versi yang diperbaiki). Jika Anda menggunakan platform vibe-coding seperti Koder.ai (koder.ai) untuk menghasilkan validator dan tes dengan cepat, kontrak impor tetap apa yang menjaga perilaku itu konsisten seiring produk berkembang.

Putuskan kontrak impor sebelum menulis aturan

Sebelum menulis satu aturan validasi pun, tentukan apa arti “input valid” untuk produk Anda. Sebagian besar bug impor adalah ketidakcocokan ekspektasi antara apa yang diunggah pengguna dan apa yang sistem Anda anggap.

Mulai dengan format, dan jelaskan secara eksplisit. “CSV” bisa berarti koma atau titik-koma, baris header atau tidak, UTF-8 atau “apa pun yang Excel hasilkan.” Untuk JSON, tentukan apakah Anda menerima satu objek, array record, atau JSON Lines (satu objek JSON per baris). Jika Anda menerima JSON bersarang, definisikan path mana yang Anda baca dan mana yang diabaikan.

Kemudian kunci kontrak field. Untuk setiap field, tentukan apakah wajib, opsional, atau opsional dengan default. Default adalah bagian dari kontrak, bukan detail implementasi. Jika country hilang, apakah Anda default ke kosong, memilih negara tertentu, atau menolak baris?

Perilaku parsing adalah tempat di mana impor "toleran" menciptakan masalah jangka panjang. Tentukan di muka seberapa ketat Anda tentang trimming spasi, normalisasi huruf besar/kecil, dan menerima varian seperti "yes"/"true"/"1". Toleransi boleh-boleh saja jika bisa diprediksi dan terdokumentasi.

Duplikat adalah keputusan kontrak lain yang mempengaruhi ketepatan dan kepercayaan. Definisikan apa yang dihitung sebagai duplikat (email yang sama, external_id yang sama, atau kombinasi field), di mana Anda mendeteksinya (di dalam file, terhadap data yang ada, atau keduanya), dan apa yang Anda lakukan saat terjadi (keep first, keep last, merge, atau reject).

Checklist kontrak yang bisa Anda tempel ke spesifikasi:

  • Format dan encoding yang diterima (delimiter CSV, JSON vs JSON Lines, dukungan nested)
  • Aturan field (required/optional/defaults, nilai yang diperbolehkan)
  • Aturan normalisasi (trim, case, format tanggal/angka)
  • Definisi dan penanganan duplikat (lingkup deteksi, perilaku yang dipilih)
  • Penempatan validasi (client, server, atau keduanya)

Contoh: mengimpor “customers.” Jika email adalah kunci unik, putuskan apakah " [email protected] " sama dengan "[email protected]", apakah email yang hilang diperbolehkan ketika external_id ada, dan apakah duplikat di dalam file harus ditolak meskipun database belum memiliki kecocokan. Setelah kontrak ini tetap, perilaku konsisten di UI dan API jauh lebih mudah, baik Anda mengimplementasikannya di Koder.ai atau di tempat lain.

Aturan validasi yang tetap terbaca dan dapat dites

Impor yang berantakan sering dimulai dari satu fungsi validate() raksasa. Pendekatan yang lebih bersih adalah aturan berlapis dengan nama jelas dan fungsi kecil. Itu membuat perubahan lebih mudah ditinjau, dan tes lebih mudah ditulis.

Mulai dengan aturan tingkat field: pemeriksaan satu nilai yang dapat lulus atau gagal sendiri (tipe, rentang, panjang, nilai yang diizinkan, regex). Buat mereka membosankan dan dapat diprediksi. Contoh: email cocok pola email dasar, age adalah integer antara 0 dan 120, status adalah salah satu dari active|paused|deleted.

Tambahkan aturan lintas-field hanya bila memang penting. Pemeriksaan ini bergantung pada beberapa field, dan bug sering tersembunyi di sini. Contoh klasik: startDate harus sebelum endDate, atau total sama dengan subtotal + tax - discount. Tulis aturan ini sehingga bisa menunjuk ke field spesifik, bukan sekadar “record invalid”.

Pisahkan aturan tingkat record dari aturan tingkat file. Aturan tingkat record memeriksa satu baris (CSV) atau satu objek (JSON). Aturan tingkat file memeriksa seluruh upload: header wajib ada, kunci unik tidak berulang across rows, jumlah kolom sesuai ekspektasi, atau file menyatakan versi yang didukung.

Normalisasi harus eksplisit, bukan “ajaib”. Tentukan apa yang Anda normalisasi sebelum memvalidasi, dan dokumentasikan. Contoh umum termasuk trimming spasi, normalisasi Unicode (agar karakter yang tampak identik dapat dibandingkan sama), dan memformat nomor telepon ke satu format penyimpanan konsisten.

Struktur yang tetap terbaca:

  • Normalize: transform input mentah menjadi bentuk kanonik.
  • Validate fields: pemeriksaan kecil dan dapat digunakan ulang per field.
  • Validate relationships: pemeriksaan lintas-field dengan target jelas.
  • Validate file rules: header, duplikat, dan dukungan versi.
  • Test each layer: unit test untuk tiap aturan, ditambah beberapa fixture end-to-end.

Versi-kan aturan Anda. Letakkan schemaVersion (atau profil impor) di file atau permintaan API. Saat Anda mengubah arti “valid”, Anda masih bisa mengimpor ekspor lama menggunakan versi lama. Pilihan itu mencegah banyak tiket “dulu bekerja kemarin”.

Rancang format pelaporan error yang dapat ditindaklanjuti

Importer yang baik gagal dengan cara yang membantu. Error samar menyebabkan retry acak dan pekerjaan dukungan yang dapat dihindari. Format error yang jelas membantu pengguna memperbaiki file dengan cepat, dan membantu Anda menyempurnakan validasi tanpa merusak client.

Mulai dengan bentuk objek error yang stabil dan pertahankan konsistensi di CSV dan JSON. Anda bisa menggunakan Claude Code untuk mengusulkan skema dan beberapa contoh realistis, lalu kunci itu sebagai bagian dari kontrak impor.

Objek error yang stabil

Anggap setiap error sebagai record kecil dengan field yang tidak berubah. Pesan bisa berkembang, tetapi kode dan lokasi harus tetap stabil.

  • code: pengenal singkat dan stabil seperti REQUIRED_MISSING atau INVALID_DATE
  • message: kalimat ramah-pengguna untuk UI
  • path: di mana masalahnya (JSON pointer seperti /customer/email, atau nama kolom seperti email)
  • row atau line: untuk CSV, sertakan nomor baris 1-based (dan opsional baris asli)
  • severity: setidaknya error dan warning

Buat error actionable. Sertakan apa yang Anda harapkan dan apa yang sebenarnya terlihat, dan bila memungkinkan tunjukkan contoh yang akan lolos. Misal: diharapkan YYYY-MM-DD, didapat 03/12/24.

Pengelompokan untuk UI dan debugging

Bahkan jika Anda mengembalikan list datar, sertakan data cukup untuk mengelompokkan error per baris dan per field. Banyak UI ingin “Baris 12 memiliki 3 masalah” lalu menyorot setiap kolom. Tim dukungan suka pengelompokan karena pola menjadi jelas (mis. setiap baris kehilangan country).

Respons ringkas bisa terlihat seperti ini:

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

Rencanakan lokalisasi tanpa mengubah error codes. Simpan code netral-bahasa dan tahan, dan anggap message sebagai teks yang dapat diganti. Jika nanti Anda menambahkan messageKey atau pesan terjemahan, client lama masih dapat bergantung pada kode yang sama untuk filter, grup, dan analytics.

Apa yang API impor harus kembalikan saat sukses dan gagal

Tame JSON type drift
Model strict types, defaults, and versioned schemas to reduce JSON surprises over time.

Untuk menghindari “impor misterius,” respons API Anda harus menjawab dua pertanyaan: apa yang terjadi, dan apa yang harus dilakukan pengguna selanjutnya.

Kembalikan ringkasan impor yang jelas (setiap kali)

Bahkan ketika ada error, kembalikan ringkasan konsisten agar UI dan tooling dukungan bisa menangani setiap impor dengan cara yang sama.

Sertakan:

  • created, updated, skipped, failed counts
  • totalRows (atau totalRecords untuk JSON)
  • mode (misal: "createOnly", "upsert", atau "updateOnly")
  • startedAt dan finishedAt timestamps
  • sebuah correlationId yang bisa diminta dukungan

correlationId itu sangat berharga. Saat seseorang melaporkan “tidak terimpor,” Anda bisa menemukan run yang tepat dan laporan error tanpa menebak-nebak.

Sertakan error yang actionable, plus cara mengambil laporan penuh

Jangan masukkan 10.000 error baris ke dalam respons. Kembalikan contoh kecil (mis. 20) yang menunjukkan pola, dan sediakan cara terpisah untuk mengambil laporan penuh bila perlu.

Buat setiap error spesifik dan stabil:

  • lokasi: nomor baris (CSV) atau path mirip JSON pointer (JSON)
  • nama field
  • kode error (machine-readable)
  • pesan (human-readable)
  • nilai yang ditolak (hati-hati dengan data sensitif)

Contoh bentuk respons (sukses dengan beberapa row gagal):

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

Perhatikan field next. Bahkan payload sukses minimal sebaiknya membantu produk melangkah: tunjukkan layar review, tawarkan retry, atau buka koleksi yang diimpor.

Definisikan idempotency agar upload ulang tidak ganda-create

Orang mencoba lagi. Jaringan gagal. Jika file yang sama diimpor dua kali, Anda ingin hasil yang dapat diprediksi.

Jadilah eksplisit tentang idempotency: terima idempotencyKey (atau hitung hash file), dan kembalikan importId yang sudah ada jika request itu pengulangan. Jika mode Anda upsert, definisikan aturan pencocokan (mis. email adalah kunci unik). Jika create-only, kembalikan “skipped” untuk duplikat, bukan “created again.”

Gunakan status yang tepat untuk kegagalan, tapi pertahankan bentuk respons

Jika seluruh request tidak valid (auth salah, content-type salah, file tak terbaca), gagal cepat dan kembalikan status: "rejected" dengan daftar error singkat. Jika file valid namun ada masalah per baris, perlakukan itu sebagai job selesai dengan failed > 0 sehingga pengguna dapat memperbaiki dan meng-upload ulang tanpa kehilangan ringkasan.

Cara menggunakan Claude Code untuk menghasilkan aturan dan contoh

Kebiasaan yang berguna: minta model menulis kontrak dalam format terstruktur, bukan sekadar prosa. “Paragraf membantu” sering melewatkan detail seperti aturan trimming, nilai default, dan apakah sel kosong berarti “missing” atau “empty”.

Gunakan prompt yang memaksa tabel yang bisa cepat ditinjau manusia dan bisa langsung dikonversi pengembang menjadi kode. Minta untuk setiap field aturan, contoh pass/fail, dan catatan eksplisit untuk hal ambigu (mis. 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).

Setelah draf pertama, perketat dengan meminta satu contoh positif dan satu contoh negatif per aturan. Itu mendorong cakupan untuk sudut rumit seperti string kosong, nilai hanya-whitespace, kolom hilang, null vs "null", integer sangat besar, notasi ilmiah, ID duplikat, dan field JSON ekstra.

Untuk skenario konkret, bayangkan mengimpor “customers” dari CSV: email wajib, phone opsional, dan signup_date default ke hari ini jika hilang. Model harus menandai kontradiksi jika Anda juga mengatakan "signup_date wajib". Ia harus mengusulkan tes seperti import_customers_missing_email_returns_row_error dan menentukan kode error serta bentuk pesan yang Anda kembalikan.

Lakukan satu kali tinjau lagi sebelum implementasi: minta model menyatakan kembali aturan sebagai checklist dan tunjukkan di mana default, field wajib, dan normalisasi mungkin saling bertentangan. Langkah review itu menangkap banyak perilaku yang memicu tiket.

Langkah demi langkah: fuzz tests untuk impor CSV dan JSON

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

Fuzz testing menghentikan “file aneh” menjadi tiket dukungan. Mulai dari set kecil file CSV/JSON yang benar, lalu hasilkan ribuan variasi yang sedikit rusak dan pastikan importer Anda bereaksi dengan aman dan jelas.

Bangun seed set, lalu mutasi

Mulai dengan korpus seed kecil contoh valid yang merepresentasikan penggunaan nyata: file valid terkecil, file tipikal, dan file besar. Untuk JSON, sertakan satu objek, banyak objek, dan struktur nested jika Anda mendukungnya.

Lalu tambahkan mutator otomatis yang mengubah satu hal pada satu waktu. Jaga mutasi dapat direproduksi dengan mencatat random seed sehingga Anda bisa memutar ulang kegagalan.

Dimensi fuzz yang menangkap sebagian besar masalah dunia nyata:

  • Masalah encoding: UTF-8 dengan BOM, urutan byte tidak valid, normalisasi campuran
  • Masalah struktur: header hilang, kolom/field ekstra, delimiter salah, trailing comma
  • Quoting dan newline: quote tidak tertutup, newline terbenam, CRLF vs LF, escaping tidak konsisten
  • Edge tipe: integer sangat besar, NaN/Infinity (JSON), string kosong vs null, padding whitespace
  • Ukuran dan batas: field sangat panjang, banyak baris, kunci berulang, array sangat dalam

Jangan berhenti pada sintaks. Tambahkan fuzz semantik juga: tukar field serupa (email vs username), tanggal ekstrem, ID duplikat, kuantitas negatif, atau nilai yang melanggar enum.

Definisikan apa arti “lulus”, lalu kunci itu

Fuzz tests hanya membantu jika kriteria lulus ketat. Importer Anda tidak boleh crash atau hang, dan error harus konsisten dan actionable.

Sekumpulan aturan lulus praktis:

  • Tidak ada crash, timeout, atau lonjakan memori di luar batas Anda
  • Error jelas dengan pointer baris/field (CSV) atau path JSON
  • Kode error stabil antara run untuk kegagalan yang sama
  • Tidak ada partial writes kecuali Anda memang mendukung partial success
  • Impor sukses menghasilkan hasil identik terlepas dari format tidak berbahaya (seperti whitespace)

Jalankan tes ini di CI pada setiap perubahan. Saat menemukan kegagalan, simpan file persis sebagai fixture dan tambahkan tes regresi agar tidak kembali.

Jika Anda menggunakan Claude Code untuk pekerjaan ini, minta ia menghasilkan fixture seed yang cocok dengan kontrak Anda, rencana mutasi, dan output error yang diharapkan. Anda masih memilih aturan, tetapi Anda mendapatkan permukaan tes luas dengan cepat, terutama untuk quoting CSV dan corner case JSON.

Perangkap umum yang menyebabkan tiket dukungan berulang

Kebanyakan tiket impor muncul dari aturan yang tidak jelas dan umpan balik yang tidak berguna.

Satu perangkap umum adalah parsing “best effort” yang tidak terdokumentasi. Jika importer Anda diam-diam memangkas spasi, menerima koma dan titik-koma, atau menebak format tanggal, pengguna membangun alur kerja di sekitar tebakan itu. Lalu perubahan kecil, atau generator file yang berbeda, merusak semuanya. Pilih perilaku, dokumentasikan, dan uji.

Pelaku lain yang sering adalah pesan error generik. “Invalid CSV” atau “Bad request” memaksa pengguna menebak. Mereka mengunggah file yang sama lima kali, dan dukungan akhirnya meminta file. Error harus menunjuk ke baris, field, alasan jelas, dan kode yang stabil.

Menolak seluruh file karena satu baris buruk juga sering menyakitkan. Kadang itu tepat (mis. impor finansial di mana partial data berbahaya). Banyak impor bisnis bisa dilanjutkan dan melaporkan ringkasan, selama Anda menawarkan pilihan eksplisit seperti strict mode vs partial import.

Masalah encoding teks menciptakan tiket yang membandel. UTF-8 adalah default yang tepat, tetapi CSV nyata sering berisi BOM, kutip keriting, atau spasi tak terputus hasil copy dari spreadsheet. Tangani ini konsisten dan laporkan apa yang terdeteksi sehingga pengguna dapat memperbaiki pengaturan ekspor mereka.

Akhirnya, mengubah kode error antara rilis merusak client dan automasi. Perbaiki redaksi jika perlu, tetapi pertahankan kode dan makna stabil. Versi-kan hanya saat benar-benar diperlukan.

Perangkap yang perlu diantisipasi:

  • Parsing “best effort” yang tidak terdokumentasi dan berubah seiring waktu
  • Error tanpa pointer baris/field dan kode error yang stabil
  • Impor all-or-nothing tanpa opsi strict vs partial
  • UTF-8, BOM, dan karakter tak terlihat tidak ditangani konsisten
  • Perubahan kode error yang merusak penanganan sisi client

Contoh: pelanggan mengekspor CSV dari Excel, yang menambahkan BOM dan memformat tanggal sebagai 03/04/2026. Importer Anda menebak MM/DD, tapi pelanggan mengharapkan DD/MM. Jika laporan error Anda menyertakan format yang terdeteksi, field yang tepat, dan perbaikan yang disarankan, pengguna bisa memperbaikinya tanpa bolak-balik.

Checklist cepat sebelum merilis importer

Bring others onto the project
Invite teammates or peers with a referral link and build your importer together in Koder.ai.

Sebagian besar masalah impor adalah ketidakcocokan kecil antara apa yang pengguna pikir file itu maksud dan apa yang sistem Anda terima. Perlakukan ini sebagai gerbang rilis.

  • Headers dan nama field: konfirmasi kolom wajib ada, nama cocok aturan Anda, dan duplikat ditolak. Putuskan apa yang dilakukan pada kolom ekstra (abaikan, peringatkan, tolak) dan jaga konsistensi.
  • Tipe data dan format: kuncikan cara parsing integer vs desimal, boolean (true/false, 0/1, yes/no), tanggal, dan timestamp (aturan timezone). Pilih satu format yang diterima per field.
  • Null dan nilai hilang: definisikan apa arti string kosong per field. Pisahkan field hilang, null eksplisit, dan teks kosong.
  • Batas ukuran dan keamanan: tetapkan batas untuk ukuran file, maksimum baris, dan panjang field maksimum. Gagal lebih awal dengan pesan jelas.
  • Error deterministik: input buruk yang sama harus menghasilkan kode error dan bentuk pesan yang sama setiap kali.

Tes praktis: gunakan satu file yang sengaja berantakan. Contoh: CSV di mana header muncul dua kali (dua kolom “email”), field boolean menggunakan “Y”, dan tanggal adalah “03/04/05”. Importer Anda tidak boleh menebak. Ia harus menerapkan aturan pemetaan terdokumentasi atau menolak dengan error spesifik.

Dua cek yang sering dilewatkan tim:

Pertama, verifikasi importer melaporkan error dengan detail lokasi cukup untuk memperbaiki file sumber. “Invalid date” tidak actionable. “Baris 42, kolom start_date: diharapkan YYYY-MM-DD, mendapat 03/04/05” itu.

Kedua, jalankan file invalid yang sama dua kali dan bandingkan hasil. Jika urutan error berubah, kode berubah, atau nomor baris bergeser, pengguna kehilangan kepercayaan. Perilaku deterministik itu membosankan, dan itu memang tujuannya.

Contoh skenario realistis dan langkah selanjutnya

Impor nyata yang umum adalah pesanan pelanggan datang dari ekspor spreadsheet. Seseorang mengekspor CSV dari sistem lama, mengeditnya di Excel, lalu mengunggahnya. Sebagian besar tiket terjadi ketika importer diam-diam “memperbaiki” data, atau ketika pesan error tidak mengatakan apa yang harus diubah.

Bayangkan file bernama orders.csv dengan kolom: order_id,customer_email,order_date,currency,total_amount.

Berikut tiga baris buruk yang realistis (sebagaimana dilihat pengguna):

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

Baris 2 memiliki email tidak valid dan format tanggal ambigu. Baris 3 kehilangan order_id, memiliki kode mata uang yang tidak didukung (US bukan USD), dan jumlah negatif.

Jika API Anda mengembalikan error, jaga bentuk konsisten dan spesifik. Berikut contoh respons yang mendukung 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]
  }
}

Partial success penting karena pengguna tidak perlu meng-upload ulang seluruh file. Alur retry sederhana: perbaiki hanya baris gagal, ekspor CSV kecil berisi baris 2 dan 3, lalu unggah ulang. Importer Anda harus memperlakukan ini sebagai idempotent saat order_id ada, sehingga “retry” memperbarui record yang sama daripada membuat duplikat.

Untuk dukungan, correlation_id adalah jalur tercepat ke diagnosis. Agen dukungan bisa meminta nilai itu, menemukan run impor di log, dan mengonfirmasi apakah parser melihat kolom ekstra, delimiter salah, atau encoding tak terduga.

Langkah selanjutnya yang membuat ini dapat diulang:

  • Gunakan Claude Code untuk menghasilkan aturan validasi, contoh baris buruk, dan kode/pesan error yang ingin Anda standarisasi.
  • Ubah contoh-contoh itu menjadi tes otomatis (termasuk fuzz tests) sehingga kasus edge baru menjadi tes yang gagal, bukan tiket baru.
  • Jika Anda membangun dengan Koder.ai, gunakan planning mode untuk menyusun kontrak impor, menghasilkan validator dan tes, lalu iterasi hingga output error tetap konsisten di CSV dan JSON.

Pertanyaan umum

Mengapa impor CSV dan JSON gagal padahal kode importer saya tampak benar?

Kebanyakan kegagalan berasal dari data dunia nyata yang berantakan, bukan dari “kode yang rusak.” Masalah CSV biasanya terkait dengan bentuk (header, delimiter, quoting, encoding), sedangkan masalah JSON biasanya terkait dengan makna (tipe, null vs kosong, nesting tak terduga). Perlakukan keduanya sebagai input yang tidak dipercaya dan validasi terhadap kontrak yang eksplisit.

Haruskah importer saya menolak seluruh file atau memperbolehkan partial success?

Tentukan tiga hasil di awal:

  • Accepted: semuanya berhasil diimpor.
  • Rejected: tidak ada yang diimpor karena file tidak dapat dipercaya (header salah, JSON tidak dapat dibaca, encoding bermasalah).
  • Partially accepted: record valid diimpor; record yang tidak valid dilewati dengan alasan yang jelas.

Pilih default (banyak produk memilih partial) dan buat konsisten di UI dan API.

Apa saja yang harus dimasukkan dalam “import contract”?

Tuliskan sebuah import contract sebelum menulis validasi:

  • Format yang diterima (delimiter CSV, header wajib, penanganan UTF-8/BOM; JSON array vs object vs JSON Lines)
  • Aturan field (required/optional/defaults)
  • Normalisasi (trim, aturan huruf besar/kecil, format tanggal)
  • Definisi dan penanganan duplikat
  • Di mana validasi dilakukan (client, server, atau keduanya)

Ini mencegah kejutan “kemarin berjalan” ketika perilaku berubah.

Bagaimana cara menangani tanggal aneh dan drift tipe ("00123" → 123, boolean yes/no)?

Standarkan pada satu format tidak ambigu per field (mis. tanggal sebagai YYYY-MM-DD). Jika Anda menerima varian, buat aturan yang eksplisit dan dapat diprediksi (mis. terima true/false/1/0, tapi jangan terima setiap tebakan spreadsheet). Hindari menebak tanggal ambigu seperti 01/02/03; minta format ISO atau tolak dengan pesan jelas.

Bagaimana cara terbaik menangani duplikat saat impor?

Putuskan:

  • Apa yang dihitung sebagai duplikat (email, external_id, atau komposit)
  • Lingkup deteksi (di dalam file, terhadap data yang ada, atau keduanya)
  • Tindakan yang diambil (keep first, keep last, merge, atau reject)

Jika pengguna dapat mengulang impor, kombinasikan ini dengan idempotency sehingga upload yang sama tidak membuat duplikat.

Bagaimana saya menyusun aturan validasi agar tetap mudah dibaca dan dites?

Gunakan lapisan daripada satu validate() besar:

  • Normalize input menjadi bentuk kanonik
  • Field-level rules (tipe, rentang, enum)
  • Cross-field rules (start < end, total sama dengan subtotal + tax - discount)
  • File-level rules (header wajib, kunci unik, versi yang didukung)

Rule kecil dengan nama jelas lebih mudah dites dan lebih aman untuk diubah.

Seperti apa bentuk pelaporan error yang baik?

Kembalikan bentuk error yang stabil dengan:

  • code (identifier yang stabil)
  • message (ramah pengguna)
  • path/field (nama kolom atau JSON pointer)
  • row/line (untuk CSV)
  • severity (error vs warning)

Buat actionable dengan menyertakan apa yang diharapkan dan apa yang ditemukan bila memungkinkan.

Apa yang harus dikembalikan API impor saya saat sukses dan saat gagal?

Selalu kembalikan ringkasan yang konsisten, bahkan saat ada error:

  • hitungan: created, updated, skipped, failed, plus totalRows/totalRecords
  • status (success, rejected, completed_with_errors)
  • timestamp (startedAt, finishedAt)
  • correlationId untuk dukungan/debugging

Untuk file besar, sertakan errorsSample kecil dan cara untuk mengambil laporan penuh nanti.

Bagaimana membuat impor idempotent agar retry tidak membuat duplikat?

Dukung retry secara eksplisit:

  • Terima idempotencyKey (atau gunakan hash file)
  • Kembalikan importId yang sama jika request diulang
  • Definisikan aturan matching untuk upsert (mis. email sebagai kunci unik)

Tanpa ini, retry pengguna normal bisa membuat duplikat.

Bagaimana cara melakukan fuzz test CSV/JSON tanpa membuat suite tes tidak terkendali?

Mulai dengan beberapa file seed yang baik, lalu buat banyak mutasi kecil (satu perubahan per kali):

  • encoding (UTF-8 BOM, byte tidak valid)
  • struktur (header hilang, kolom ekstra, delimiter salah)
  • quoting/newlines (quote tidak tertutup, newline terbenam)
  • edge tipe (angka sangat besar, kosong vs null, NaN/Infinity di JSON)
  • batas ukuran (field sangat panjang, nesting dalam)

Sebuah fuzz test "lulus" bila importer tidak crash/hang dan selalu mengembalikan error yang deterministik dan actionable.

Related posts