JSON Toolkit

JSON ke CSV: dari mana datangnya pengepala dan mengapa nilai berubah

Inti pati: Sembilan eksperimen pada penukar sebenar: strategi "kunci rekod pertama" kehilangan medan secara senyap, null, ketiadaan dan rentetan kosong semuanya menjadi sel kosong, integer 20 digit hilang ketepatan seawal JSON.parse, dan titik dalam kunci membuat dua laluan berbeza berlanggar dalam lajur yang sama. Bagaimana pengepala dibina, nilai mana yang terherot dan cara memilih strategi mengikut kegunaan hilir.

Lanjutan~6 min bacaanDiterbitkan 2026-11-04Dikemas kini 2026-11-04
Strategi pengepala dan kesetiaan nilai dalam penukaran JSON ke CSV

Apabila penukaran JSON ke CSV kehilangan data, hampir tidak pernah berlaku pada langkah "penukaran" itu sendiri. Kehilangan berlaku dalam dua soalan yang tidak pernah ditanya: siapa yang memutuskan pengepala, dan adakah setiap sel masih dikenali sebagai nilai yang asalnya?

Satu medan hilang dalam tiga puluh saat

Banyak penukar — termasuk saluran jq yang idiomatik — mengambil pengepala hanya daripada rekod pertama. Hasilkan semula kesannya dalam Python:

data = [{"id": 1, "name": "A"}, {"id": 2, "email": "b@x.com"}]
first_keys = list(data[0].keys())          # ['id', 'name']
rows = [[r.get(k, "") for k in first_keys] for r in data]
# E-mel rekod kedua hilang tanpa ralat mahupun amaran

Kunci email tiada dalam pengepala: dia tidak berhak langsung menjadi sel kosong — lajur tidak pernah dicipta, dan nilai dibuang secara senyap. Pembetulannya ialah kesatuan kunci: lalui semua rekod dan bina satu lajur bagi setiap kunci yang muncul di mana-mana. Data yang sama melalui kesatuan menghasilkan pengepala id,name,email, dengan sel kosong di tempat name tiada — dan tiada apa-apa yang hilang.

Penukar terus di halaman /convert/csv kami menggunakan strategi ini tepat. Dengan input [{"id":1,"name":"A"},{"id":2,"email":"b@x.com"}], ia menghasilkan:

id,name,email
1,A,
2,,b@x.com

Kunci disusun mengikut kemunculan pertama, medan yang tiada menjadi sel kosong. jsonoperations dan jsonbeam kedua-duanya menggelar ini "pembetulan bug klasik" — tetapi "guna kesatuan" hanya separuh cerita. Kesatuan ada harganya sendiri; itulah bahagian seterusnya.

Tiga cara membina pengepala — dan siapa yang sesuai dengan setiap satu

Strategi pengepala Cara dibina Kekuatan Harga
Kunci rekod pertama Hanya rekod pertama dibaca Lajur sedikit, stabil, satu baris jq Medan baharu rekod seterusnya hilang secara senyap
Kesatuan kunci Semua rekod dibaca Tiada medan hilang Lajur jarang dan banyak sel kosong bila bentuk berbeza
Senarai lajur tak tersirat Ditakrif manual atau oleh skema Terkawal sepenuhnya, boleh diulang Perlu penyelenggaraan; medan baharu memerlukan kemas kini manual

Kriteria pilihan bukan "yang mana lebih canggih" tetapi apa yang pihak penerima lakukan dengan CSV ini:

  • Rakan sekerja yang melihat sepintas: kunci rekod pertama memadai, bentuk rekod biasanya seragam.
  • Laporan atau saluran data: kesatuan kunci ialah syarat minimum — sel kosong itu sendiri maklumat.
  • Eksport automatik berkala: senarai lajur tak tersirat. Herotan bentuk (medan baharu dari hulu, nama kunci ditukar) mesti gagal dengan bising, bukan senyap-senyap menghasilkan jadual yang tiada siapa perasan salah.

Pilihan ketiga paling terabai. Dalam automasi, "penukaran berjaya" dan "penukaran betul" ialah dua kenyataan berbeza — dan senarai lajur tak tersirat ialah satu-satunya mekanisme yang memisahkan keduanya.

Apabila kunci mengandungi titik, laluan pemipihan berlanggar

Pemipihan dengan notasi titik mengubah {"a": {"b": 2}} kepada lajur a.b. Tetapi bagaimana jika kunci itu sendiri mengandungi titik? Diuji dengan pandas:

import pandas as pd
d = [{"a.b": 1, "a": {"b": 2}}]
pd.json_normalize(d, sep=".")
# Hanya satu lajur terselamat: ['a.b'] — dua kunci yang benar-benar berbeza berlanggar pada laluan yang sama

Kunci literal a.b dan laluan bersarang a → b menghasilkan nama lajur yang sama, satu menindih yang lain, dan data rosak secara senyap. Contoh ini direka, tetapi berlaku juga dengan data sebenar: nama metrik pemantauan (cpu.usage) dan medan log (error.type) memang suka titik.

Dua penawar:

  1. Tukar pemisah. sep="_" atau pemisah sendiri — selepas memastikan kunci asal tidak pernah memuatinya.
  2. Tukar notasi laluan. JSON Pointer menggunakan / sebagai pemisah (/a/b); penukar Excel toolvore mengambil jalan ini. Ia ada kelas kekaburan yang sama — kunci dengan / ditulis ~1 — tetapi peraturan pelarian dinormalkan dalam RFC 6901, bukan dicipta sendiri oleh setiap alat.

Apapun pilihan anda, tulis peraturannya dalam dokumentasi eksport. Pengepala CSV ialah "skema" tunggal yang dibawa data ini; pembaca tidak akan jumpa peraturan pemipihan anda di tempat lain.

Tatasusunan: tiga strategi, setiap satu kehilangan perkara berbeza

Tatasusunan ialah halangan sebenar perjalanan JSON ke CSV: satu sel tidak boleh memuatkan banyak nilai. Tiga strategi, dengan kehilangan yang disahkan dalam amalan:

Strategi Bentuk keluaran Yang hilang Sesuai untuk
JSON dalam sel Tatasusunan disirikan sebagai rentetan JSON dalam sel Alat jadual tidak boleh menapis atau mengagregat unsur Kesetiaan dahulu, pemeriksaan manual
Lajur berindeks tags.0, tags.1, satu lajur setiap satu Bilangan lajur meletup mengikut tatasusunan terpanjang; banyak sel kosong Tatasusunan kecil panjang tetap
Baris dileraikan Satu baris setiap unsur, medan induk diduplikasi Bengkak baris; tingkah laku tatasusunan kosong perlu ditetapkan berasingan Analisis terperinci, agregasi setiap unsur

Penukar /convert/csv dan /convert/table kami menggunakan JSON dalam sel. Input [{"orderId":"A001","items":[{"sku":"X1","qty":2},{"sku":"Y9","qty":1}]}] menghasilkan:

orderId,items
A001,"[{""sku"":""X1"",""qty"":2},{""sku"":""Y9"",""qty"":1}]"

Perlu baris dileraikan, pandas record_path melakukannya terus:

orders = [{"orderId": "A001", "total": 99,
           "items": [{"sku": "X1", "qty": 2}, {"sku": "Y9", "qty": 1}]}]
items = pd.json_normalize(orders, record_path=["items"],
                          meta=["orderId", "total"], sep=".")
# Dua baris butiran; orderId dan total diduplikasi pada setiap satu

Dalam peletupan ada tiga perangkap yang perlu diputuskan awal: meleraikan beberapa tatasusunan sekaligus membina hasil darab Cartesius; tatasusunan kosong secara lalai tidak menghasilkan sebarang baris (senarai pelanggan anda kehilangan orang); dan medan induk diduplikasi memerlukan penyahduplikasi semasa mengagregat mengikut orderId di hilir. Panduan convertcsvonline meletakkan "tetapkan kegranulan dahulu" sebagai langkah pertama tepat kerana itu — sebaik kegranulan dikunci, ketiga-tiga soalan masing-masing ada satu jawapan.

Diuji: nilai yang keluar dari penukaran dalam keadaan berubah

Ujian kesetiaan dijalankan pada penukar sebenar kami (Node v22.13.1 + papaparse, pelaksanaan yang sama seperti /convert/csv):

1. null, ketiadaan dan rentetan kosong semuanya menjadi sel kosong. Input [{"a":null},{"b":""},{"c":1}] — ketiga-tiga sel keluar kosong. CSV tidak mempunyai tiga keadaan, hanya "ada aksara" dan "tiada aksara". Selepas satu pusingan pergi-balik, ketiga-tiga terbaca ""; semantik asal tidak boleh dipulihkan.

2. Objek dan tatasusunan bersarang menjadi rentetan JSON. Petikan digandakan mengikut RFC 4180 ({""name"":""张三""}), dan dengan menampal sel ke mana-mana penghurai JSON, nilai kembali — itulah sebabnya JSON dalam sel mengekalkan kesetiaan.

3. Integer 20 digit hilang ketepatan seawal ketika penghuraian — dan kesalahannya bukan pada CSV. Input "id": 9007199254740993; dalam CSV sudah tertera 9007199254740992. JSON.parse dalam JavaScript menggunakan double IEEE 754: kehilangan berlaku semasa penghuraian, sebelum penukar CSV mana-mana. Python json.load memeliharanya sepenuhnya. Medan jenis pengecam (ID snowflake, nombor pesanan) sepatutnya tiba sebagai rentetan terus dari pengeluar. Lanjutan mengenai ketepatan nombor di mengapa nombor besar hilang ketepatan.

4. Sifar pendahuluan dalam rentetan selamat pada lapisan teks CSV. "phone": "00123" kekal 00123 dalam CSV, kerana ia rentetan dari mula hingga akhir dan tiada apa yang menyalaknya. Yang menyalak sifar ialah langkah seterusnya, apabila Excel menganggap sel sebagai nombor — lihat empat cara menukar JSON ke Excel.

5. Medan mengandungi koma, petikan atau baris baharu. papaparse mematuhi RFC 4180: petik medan itu, gandakan petikan dalaman. "He said \"hi\", ok" keluar sebagai "He said ""hi"", ok" dan melalui pusingan pergi-balik tanpa cedera. Penyiri tulisan tangan yang memintas pustaka hampir selalu gagal tepat di situ.

Pusingan pergi-balik: apa yang diubah suis inferens

CSV → JSON perlu meneka jenis bagi setiap sel. Penukar kami mematikan inferens jenis secara lalai dan memulangkan semuanya sebagai rentetan:

[{ "id": "9007199254740992", "phone": "00123" }]

Dengan typeInference aktif, id menjadi nombor (ketepatan sudah hilang) sementara phone kekal rentetan — peraturan inferens mengecualikan bentuk bersifar pendahuluan seperti 010, yang bukan literal nombor yang sah, jadi rentetan itu terselamat secara kebetulan.

Hafal asimetri ini: inferens mati dalam kes paling teruk hanya merampas jenis; inferens hidup boleh merampas data. Lajur yang perlukan nombor ditukar dengan takrif lajur tak tersirat, bukan dipercayakan kepada inferens menyeluruh. Pelaksanaan rowsToRecords dalam artikel terdahulu kami JSON, CSV dan data jadual tepat prinsip ini dalam bentuk kod.

Memilih strategi mengikut penerima: jadual keputusan

Siapa menerima CSV Strategi pengepala Pengendalian tatasusunan Jenis
Rakan sekerja yang membuka sekali Kesatuan kunci JSON dalam sel Tanpa inferens
Excel / pelaporan Kesatuan kunci JSON dalam sel, atau lajur berindeks jika panjang tetap Lajur pengecam dipaksa sebagai teks
Import ke pangkalan data Senarai lajur tak tersirat Jadual master/detail berasingan, atau peletupan Takrif lajur tak tersirat
BI / agregasi Senarai lajur tak tersirat Baris dileraikan, kegranulan = unit analisis terkecil Takrif lajur tak tersirat
Saluran automatik Senarai lajur tak tersirat JSON dalam sel, peletupan di hilir Inferens mati, penukaran lajur demi lajur

Undang-undang bersama: semakin dekat kepada manusia, semakin boleh dilonggarkan; semakin dekat kepada mesin, semakin banyak mesti tak tersirat.

Senarai semak untuk disalin

  • [ ] Pengepala datang daripada kesatuan kunci penuh atau senarai tak tersirat? Jika tidak, mampu buktikan tiada rekod yang kehilangan medan?
  • [ ] Bolehkah kunci mengandungi titik atau palang condong? Langgar dengan pemisah pemipihan sudah diperiksa?
  • [ ] Strategi tatasusunan sudah didokumenkan? Tingkah laku tatasusunan kosong sudah diputuskan?
  • [ ] Bagi null, ketiadaan dan rentetan kosong: apakah yang dibaca penerima bagi setiap satu? Pilih satu peraturan dan bekukan.
  • [ ] Lajur jenis pengecam (ID, nombor pesanan, telefon) merentang sebagai rentetan dari hulu ke hilir?
  • [ ] Selepas peletupan, bilangan baris sama dengan hasil tambah panjang tatasusunan? Disemak secara sampel?
  • [ ] Medan contoh dengan koma, petikan dan baris baharu melalui pusingan pergi-balik tanpa cedera?
  • [ ] Inferens jenis menyeluruh dimatikan semasa import semula, dengan takrif tak tersirat bagi lajur berangka?

Hanya apabila kesemuanya lapan ada jawapan jelas, CSV ini "betul" — bukan sekadar "berjaya ditukar".

FAQ

Mengapa penukar tidak meratakan objek bersarang kepada lajur secara lalai?

Pemipihan melepaskan bilangan lajur daripada kawalan: sarangan dalam menghasilkan nama seperti user.address.geo.lat, dan digabungkan dengan kesatuan kunci, satu rekod berbentuk lain sahaja menambah tumpukan lajur. Rentetan JSON dalam sel mengekalkan kesetiaan dan bilangan lajur yang stabil; pipihkan secara tak tersirat apabila diperlukan.

Apa perlu dibuat jika pengepala mengandungi nama lajur pendua?

Langgar dua kunci berbeza selepas pemipihan (seperti a.b menentang a→b bersarang) diselesaikan di hulu: tukar pemisah atau beralih kepada JSON Pointer. Bagi pendua dalam objek sama, penukar biasanya menyimpan nilai terakhir; pendua dalam pengepala bergantung pelaksanaan — unparse papaparse tidak menyahduplikasi, dan Excel semasa membuka secara senyap menggabungkan atau membuang pendua. Itulah sebabnya ia dalam senarai semak.

Medan induk diduplikasi selepas peletupan — adakah itu bug?

Bukan — itu reka bentuk. Baris dileraikan ialah baris butiran, dan baris butiran mesti boleh disambung semula ke rekod induk melalui kunci. Agregat di hilir mengikut kunci induk; jika saiz membimbangkan, eksport fail butiran dan satu jadual master berasingan.

Bagaimana memastikan penukaran saya tidak kehilangan sebarang medan?

Lakukan audit kunci: kira kesatuan semua kunci dalam JSON sumber, kemudian set pengepala lajur CSV, dan ambil beza. Beza tak kosong bermakna medan hilang. Dalam saluran berkelompok, kodkan ini sebagai assert dalam ujian: sebarang penukaran penukar yang mula kehilangan medan akan gagal secara automatik.