Zo vlak je geneste JSON af naar CSV: 5 strategieën & beslissingsmatrix
Het geometrieprobleem
Je loopt elke keer tegen dezelfde muur op. Een API geeft geneste JSON terug en de analist op Slack wil gewoon een spreadsheet. mongoexport produceert $oid-wrappers en drie lagen metadata, en BigQuery verwacht een platte tabel. Geneste JSON afvlakken naar CSV is geen syntaxisprobleem. Het is een geometrieprobleem. JSON is een boom, CSV is een rooster, en je kunt geen boom in een rooster zetten zonder te kiezen hoe de takken samenvouwen.
Er bestaan precies vijf samenvouw-strategieën. Kies de verkeerde en je levert 200 kolommen aan Excel, verliest precisie op een Twitter-ID, of breekt de heen-en-terug-conversie waar je pipeline op leunt. Kies de juiste en de conversie is een one-liner.
| Strategie | One-liner | Geschikt voor |
|---|---|---|
| Puntnotatie | customer.address.city | Excel/Sheets-analyse |
| Underscore | customer_address_city | SQL-vriendelijke kolommen |
| Geïndexeerde arrays | items.0.sku, items.1.sku | Arrays met vaste lengte |
| Rij-explosie | Herhaal ouder voor elk kind | Pandas/BigQuery-analytics |
| Stringify | "{\"city\":\"Seattle\"}" in één cel | Verliesvrije heen-en-terug |
Hieronder volgt elke strategie, een beslissingsmatrix per consument (Excel, Pandas, BigQuery, Postgres) en vier echte payloads waar de juiste strategie niet de voor de hand liggende is. Als je ook het algemene bidirectionele overzicht nodig hebt (parserbibliotheken, streaming, encoding-valkuilen), zie de CSV naar JSON omzetten.
Waarom geneste JSON niet in CSV past
JSON draagt drie soorten structuur die CSV mist. Hiërarchie is een object binnen een object. Sequentie is een array. Gemengd is de combinatie: arrays van objecten, objecten met arrays, arrays van arrays. Een typische e-commerce-order is alle drie tegelijk.
CSV heeft precies twee dimensies: rijen en kolommen. Er is geen derde as voor “deze kolom bevat drie kinderen.” Wanneer je een rooster eist van een boom, moet er iets wijken. Spreid de kinderen over meer kolommen (en leef met namen als items.0.options.0.value), spreid ze over meer rijen (oudervelden herhalen), of pers ze in één cel als tekst en behandel ze niet langer als structuur.
Elke strategie hieronder beantwoordt die vraag anders. Sommige behouden leesbaarheid en verliezen veiligheid bij heen-en-terug. Andere doen het omgekeerde. Geen enkele is universeel. Stem het antwoord af op wie het bestand vervolgens leest.
5 afvlak-strategieën vergeleken
Strategie 1: Puntnotatie (customer.address.city)
Puntnotatie loopt van wortel naar blad en gebruikt . om sleutels samen te voegen. Elk genest object wordt één kolom per blad, met het pad gecodeerd in de kolomnaam.
{ "customer": { "address": { "city": "Seattle" } }, "email": "alice@example.com" }
wordt
customer.address.city,email
Seattle,alice@example.com
In Pandas dekt één regel het:
import pandas as pd
data = [{"customer": {"address": {"city": "Seattle"}}, "email": "alice@example.com"}]
df = pd.json_normalize(data, sep='.')
df.to_csv("out.csv", index=False)
In JavaScript volstaat een kleine recursieve functie:
function flattenDot(obj, prefix = '', acc = {}) {
for (const [k, v] of Object.entries(obj)) {
const key = prefix ? `${prefix}.${k}` : k;
if (v && typeof v === 'object' && !Array.isArray(v)) {
flattenDot(v, key, acc);
} else {
acc[key] = v;
}
}
return acc;
}
Voordelen: leesbaar voor mensen, standaard in Pandas, behoudt het oorspronkelijke pad. Nadelen: kolomnamen kunnen lang worden (Kubernetes-specs produceren namen als spec.template.spec.containers.0.resources.limits.memory), en de punt wordt dubbelzinnig als een echte sleutel een . bevat (de event-parameters van Google Analytics 4 doen dat).
Strategie 2: Underscore-notatie (customer_address_city)
Zelfde idee, ander scheidingsteken. Vervang . door _ en het resultaat is SQL-veilig: SELECT customer_address_city FROM events werkt zonder de identifier te quoten. BigQuery, Snowflake en Postgres geven hier alle drie de voorkeur aan.
import pandas as pd
df = pd.json_normalize(data, sep='_')
De keuze tussen punt en underscore gaat puur over de downstream-tool. Excel-analisten lezen punten natuurlijker; SQL-engines accepteren underscore zonder klagen. Wissel door één argument te veranderen.
Voordelen: SQL-veilige kolomnamen, BigQuery-conforme identifiers, geen quoten nodig. Nadelen: dubbelzinnigheid blijft als een sleutel een _ bevat (minder vaak dan . maar nog steeds mogelijk).
Strategie 3: Geïndexeerde arrays (items.0.sku, items.1.sku)
Objecten vlakken netjes af omdat sleutels uniek zijn. Arrays niet, omdat hun lengte onbegrensd is. De geïndexeerde strategie behandelt array-posities als padsegmenten: items[0] wordt items.0.
{ "id": "ord-001", "items": [{"sku": "A"}, {"sku": "B"}] }
wordt
id,items.0.sku,items.1.sku
ord-001,A,B
Dit is het standaardgedrag van Flatten in onze JSON naar CSV Omzetter. Elk blad krijgt zijn eigen kolom; de positie wordt vastgelegd in de naam.
Voordelen: elke waarde krijgt een eigen cel, positie behouden, geen rij-duplicatie. Nadelen: het kolomaantal explodeert (100 items = 100 kolommen); rijen met verschillende array-lengtes produceren rafelige tabellen; downstream-aggregatie breekt (geen SUM(items.*.qty)).
Strategie 4: Rij-explosie (array naar meerdere rijen)
In plaats van de tabel breder te maken om de array te passen, maak je hem langer. Herhaal de oudervelden eenmaal per array-element en laat elk element een eigen rij worden.
{ "order_id": "ord-001", "customer": "Alice", "items": [{"sku": "A", "qty": 2}, {"sku": "B", "qty": 1}] }
wordt
order_id,customer,items.sku,items.qty
ord-001,Alice,A,2
ord-001,Alice,B,1
In Pandas doet één regel zowel de explosie als de normalisatie:
import pandas as pd
orders = [{"order_id": "ord-001", "customer": "Alice",
"items": [{"sku": "A", "qty": 2}, {"sku": "B", "qty": 1}]}]
df = pd.json_normalize(orders, record_path='items', meta=['order_id', 'customer'])
df.to_csv("orders.csv", index=False)
In SQL doet UNNEST hetzelfde:
SELECT order_id, item.sku, item.qty FROM orders, UNNEST(items) AS item;
Voordelen: Pandas en BigQuery verwerken deze vorm ingebouwd, aggregaties werken (GROUP BY order_id), het schema blijft smal. Nadelen: oudervelden dupliceren in elke kindrij (opslagopbouw), de 1-op-veel-grens is impliciet (je hebt een order_id nodig), en twee arrays op hetzelfde niveau produceren een Cartesisch product tenzij je ze zorgvuldig UNNEST-t.
Strategie 5: Stringify (JSON-in-cel)
De radicale optie: vlak helemaal niet af. Serialiseer de hele geneste waarde als JSON-string en zet hem in één cel. De buitenste tabel blijft plat; de structuur blijft woordelijk binnenin bewaard.
{ "id": "ord-001", "items": [{"sku": "A"}, {"sku": "B"}] }
wordt
id,items
ord-001,"[{""sku"":""A""},{""sku"":""B""}]"
Dit is de Stringify-modus in onze JSON naar CSV Omzetter. Het kolomaantal explodeert nooit, de oorspronkelijke vorm blijft byte-voor-byte behouden, en de terugweg reconstrueert de invoer exact.
Voordelen: 100% verliesvrij, voorspelbaar kolomaantal, veilig voor heen-en-terug in combinatie met Infer types op de terugweg. Nadelen: Excel-gebruikers zien geëscapete aanhalingstekens, SQL-engines hebben JSON-functies nodig om in de waarde te zoeken (JSON_EXTRACT_SCALAR in BigQuery, ->>'key' in Postgres), en spreadsheet-formules komen niet bij de cel-inhoud.
5 strategieën naast elkaar
Dezelfde invoer over alle vijf: {"id":"ord-001","customer":{"name":"Alice"},"items":[{"sku":"A","qty":2},{"sku":"B","qty":1}]}.
| Strategie | Kolommen | Veilig voor heen-en-terug | Beste consument |
|---|---|---|---|
| Puntnotatie | groeit met array | Nee | Excel-analist |
| Underscore | groeit met array | Nee | SQL-warehouse |
| Geïndexeerde arrays | 2 per array-positie | Nee (dubbelzinnig op de terugweg) | Arrays met vaste lengte |
| Rij-explosie | smal, 1 rij per kind | Gedeeltelijk (sleutel nodig) | Pandas / BigQuery |
| Stringify | vast | Ja | Pipeline heen-en-terug |
Beslissingsmatrix: welke strategie voor welke consument
Zoek eerst de consument op, lees daarna de aanbevolen strategie af.
| Consument | Aanbevolen strategie | Waarom |
|---|---|---|
| Excel / Sheets (analist) | Punt + Stringify voor grote arrays | Leesbare kolomnamen; grote arrays exploderen het werkblad niet |
| Excel-EU (DE/FR/IT/ES) | Punt + ;-scheidingsteken + UTF-8 BOM | Puntkomma vereist; BOM voorkomt encoding-vervorming |
Pandas (json_normalize + explode) | Underscore + Rij-explosie | SQL-vriendelijke kolommen; explode speelt goed samen met groupby |
| BigQuery / Snowflake | TSV + Stringify of Rij-explosie | Tab vermijdt quote-valkuilen; JSON_EXTRACT bevraagt de cel |
PostgreSQL COPY | RFC 4180 + Underscore + plat | SQL-veilige kolommen; strikt RFC-quoten |
| MongoDB → BigQuery ETL | NDJSON direct laden, sla CSV over | BigQuery laadt NDJSON ingebouwd; CSV is een omweg |
Excel / Google Sheets: de locale-val
Excel-kolomnamen hebben geen praktische lengtelimiet. De echte valkuilen zijn er drie.
Ten eerste, de locale-splitsing. Europese Excel (Duitsland, Frankrijk, Italië, Spanje) verwacht ; als scheidingsteken omdat , het decimaalteken is. Een komma-gescheiden CSV opent met elke rij samengeperst in kolom A. De Excel-preset in onze JSON naar CSV Omzetter wisselt met één klik naar ; + CRLF + UTF-8 BOM.
Ten tweede, wetenschappelijke notatie. Excel ziet 9007199254740993 en rendert 9.00719925474E+15. Sla grote gehele getallen op als strings in de bron-JSON en zet BOM aan zodat Excel de cel als tekst behoudt. Onze omzetter detecteert grote gehele getallen automatisch.
Ten derde, de praktische kolomlimiet. Excel ondersteunt theoretisch 16.384 kolommen, maar alles boven ~500 wordt onhanteerbaar. Gebruik Stringify voor de zware subbomen of pre-projecteer met jq voor de conversie.
Pandas: json_normalize + explode
Het standaardpatroon voor geneste arrays is record_path + meta in één doorgang:
import pandas as pd
orders = [{
"order_id": "ord-001",
"customer": {"name": "Alice", "city": "Seattle"},
"items": [{"sku": "SKU-100", "qty": 2}, {"sku": "SKU-205", "qty": 1}]
}]
df = pd.json_normalize(orders, record_path='items',
meta=['order_id', ['customer', 'name'], ['customer', 'city']], sep='_')
df.to_csv("orders.csv", index=False)
De uitvoer is één rij per item met order_id, customer_name en customer_city herhaald. Dit verslaat eerst explode draaien en daarna json_normalize: record_path slaat de tussenliggende object-kolom over en meta laat je sturen welke oudervelden meereizen. Voor invoer waar array-elementen geneste objecten bevatten, stel max_level= in om de diepte te begrenzen.
BigQuery / Snowflake: TSV + JSON-in-cel
LOAD DATA van BigQuery is streng over CSV-quoten en interpreteert vaak bestanden verkeerd met komma’s binnen gequote tekst. TSV is veiliger omdat tabs vrijwel nooit voorkomen binnen tekstvelden:
bq load --source_format=CSV --field_delimiter='\t' \
dataset.orders gs://bucket/orders.tsv \
order_id:STRING,customer:STRING,items:STRING
Wanneer je geneste data laadt als Stringified JSON in één kolom, bevraagt BigQuery deze nog steeds met JSON_EXTRACT_SCALAR:
SELECT order_id, JSON_EXTRACT_SCALAR(items, '$[0].sku') AS first_sku
FROM dataset.orders;
Snowflake biedt dezelfde mogelijkheid via VARIANT, met padquery’s als items:0.sku::STRING. In beide engines verslaat Stringify + JSON-padquery’s volledige afvlakking wanneer geneste arrays groot of variabel van lengte zijn.
PostgreSQL COPY: strikt RFC 4180
COPY ... FROM ... WITH (FORMAT csv, HEADER true) is de strengste RFC 4180-lezer die je gewoonlijk tegenkomt. Twee gedragingen halen mensen onderuit.
Ten eerste accepteert COPY geen UTF-8 BOM. De byte order mark wordt een letterlijk voorvoegsel op de eerste kolomnaam (id in plaats van id), en elke query die id aanhaalt mislukt stil. Zet BOM uit voor Postgres-doelen.
Ten tweede kan COPY geneste data niet ingebouwd verwerken. Of explodeer arrays naar meerdere rijen voor het laden, of definieer de bestemming als jsonb en gebruik stringify voor de geneste waarde:
CREATE TABLE orders (order_id text PRIMARY KEY, customer text, items jsonb);
COPY orders FROM '/tmp/orders.csv' WITH (FORMAT csv, HEADER true);
SELECT order_id, items->0->>'sku' AS first_sku FROM orders;
Voor pipelines die al van begin tot eind JSON spreken, sla CSV over en gebruik COPY ... FROM ... WITH (FORMAT text) met JSON-line-invoer in plaats daarvan.
Doorlopen van echte payloads
Doorloop 1: E-commerce-orders (klant + items-array)
Een typische order combineert geneste klantinfo met een items-array van variabele lengte:
[{ "id": "ord-001",
"customer": { "name": "Alice", "address": {"city": "Seattle", "country": "US"} },
"items": [{"sku": "SKU-100", "qty": 2}, {"sku": "SKU-205", "qty": 1}] }]
De juiste strategie hangt af van wie het bestand leest. Finance wil één rij per item om de omzet per SKU te berekenen; dat is de explosie-strategie, die twee rijen produceert met id en customer.name herhaald. Operations wil één rij per order voor fulfilment-dashboards; dat is puntnotatie met Stringified items zodat de array het kolomaantal niet opblaast. Dezelfde invoer, twee uitvoeren, beide correct voor hun consument.
Probeer het direct: plak de payload in onze JSON naar CSV Omzetter en wissel tussen Flatten en Stringify in de Nested-optie. Het voorbeeld “Nested E-commerce Orders” laadt dezelfde vorm.
Doorloop 2: GitHub Issues API (labels-array + user-object)
Het /repos/{owner}/{repo}/issues-endpoint geeft een gemengde geneste vorm terug:
[{ "id": 1001, "title": "Bug: login 404", "state": "open",
"labels": ["bug", "priority:high"], "user": {"login": "alice"} }]
user is een object met één nuttig veld; labels is een string-array van onbegrensde lengte. De pragmatische afvlakking is hybride: puntnotatie op user (je geeft alleen om user.login) en inline-join op labels naar één cel gescheiden door ;:
id,title,state,labels,user.login
1001,Bug: login 404,open,bug;priority:high,alice
Je kunt niet zowel “voeg arrays samen in een cel” als “vlak objecten af met punten” in één strategie vangen. Onze omzetter regelt de object-afvlakking automatisch; voorverwerk de labels met jq (map(.labels = (.labels | join(";")))) of accepteer het standaard array-stringify-gedrag.
Doorloop 3: MongoDB mongoexport ($oid + metadata)
mongoexport --jsonArray produceert Extended JSON-wrappers:
[{ "_id": {"$oid": "6634a1b2c3d4e5f600000001"},
"email": "alice@example.com",
"metadata": { "signupDate": "2026-01-15T10:30:00Z",
"preferences": {"newsletter": true, "theme": "dark"} } }]
De $oid-wrapper produceert een kolom met de letterlijke naam _id.$oid, die de meeste SQL-engines afwijzen. Voorverwerk met jq om hem uit te pakken:
mongoexport --collection=users --jsonArray | jq 'map(._id = ._id."$oid")' > users.json
Voor het diep geneste metadata.preferences-blok kies je op basis van de consument. Analisten-export: vlak het geheel af met puntnotatie; metadata.preferences.theme leest prima. Pipeline heen-en-terug: gebruik stringify op metadata om de structuur intact te houden. Voor volledige jq-patronen die met CSV-pipelines samengaan, zie onze jq spiekbriefje.
Doorloop 4: Kubernetes Pod Spec (diep genest)
Een respons van kubectl get pod -o json is een worstcase voor platte strategieën. De structuur gaat regelmatig zes lagen diep (spec.template.spec.containers.0.resources.limits.memory). Naïeve punt-afvlakking produceert kolomnamen van meer dan 70 tekens en 200+ uitvoerkolommen. Twee strategieën werken.
Pre-projecteer met kubectl jsonpath. Kies alleen de velden die je echt nodig hebt:
kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[0].image}{"\t"}{.status.phase}{"\n"}{end}' > pods.tsv
Gebruik stringify op de spec, vlak de metadata af. Houd metadata (name, namespace, labels) plat en zet spec om in één cel met stringify:
kubectl get pods -o json | jq 'map({name: .metadata.name, namespace: .metadata.namespace, spec: (.spec | tostring)})'
Plak daarna in de omzetter met Flatten-modus. De spec-kolom wordt één JSON-cel; de metadata-kolommen blijven leesbaar. Vermijd het anti-patroon kubectl get pod -o json | json-to-csv flatten zonder pre-projectie. Het kolomaantal wordt onwerkbaar.
Veilig voor heen-en-terug: afvlakken is lossy, stringify is verliesvrij
Een stelling die de meeste gidsen overslaan: puntnotatie, underscore-notatie, geïndexeerde arrays en rij-explosie zijn allemaal eenwegprojecties. Zodra je met een van deze afvlakt, kan de oorspronkelijke JSON niet perfect worden gereconstrueerd uit alleen de CSV.
Tegenvoorbeelden zijn makkelijk te bouwen. Een kolom met de naam customer.address.city is dubbelzinnig tussen {"customer": {"address": {"city": "..."}}} en {"customer": {"address.city": "..."}}. Geïndexeerde arrays lijken omkeerbaar, maar CSV kan niet zeggen of items.0.sku moet reconstrueren tot een array of een object met een numerieke sleutel. Rij-explosie vereist een group-by-sleutel; zonder order_id kun je niet zien welke rijen bij dezelfde ouder hoorden.
Alleen Stringify overleeft de heen-en-terug. De geneste waarde wordt woordelijk bewaard als JSON-string, dus de omgekeerde omzetter leest de cel, leest die als JSON in, en plaatst het origineel intact terug. Zet om met Stringify, sla de CSV op, plak in onze CSV naar JSON Omzetter, zet Infer types aan, en je krijgt bytes die identiek zijn aan de invoer.
De praktische regel: pipeline heen-en-terug → Stringify. Eenmalige analyse of rapportage → punt, underscore of explosie op basis van de consument.
Hoe pak je dit aan in onze browser-tool
De JSON naar CSV Omzetter ontsluit twee van de vijf strategieën direct: Flatten (combineert puntnotatie en geïndexeerde arrays) en Stringify (behoudt structuur binnen een cel). De andere drie (underscore, rij-explosie, SQL-target-presets) liggen één voorverwerkingsstap verderop.
Een typische sessie kost vijf klikken:
- Valideer de invoer met onze JSON Formatter zodat syntaxfouten geen stille conversiefouten worden.
- Plak de JSON in de JSON naar CSV Omzetter. De conversie loopt direct.
- Zet Nested op Flatten voor punt- en geïndexeerde sleutels, of op Stringify om arrays en objecten in enkele cellen te houden.
- Kies een preset: RFC 4180 voor pipelines, Excel voor EU-spreadsheets, TSV voor warehouses, Pipe voor komma-zware tekst.
- Klik op Swap direction en gebruik de CSV naar JSON Omzetter met Infer types aan om een Stringify-heen-en-terug te verifiëren.
Alles loopt in je browser. PII, interne exports en productie-secrets verlaten de pagina nooit; er zijn nul netwerkverzoeken na het laden van de pagina. Veilig voor gevoelige data waar uploaden naar een externe site geen optie is.
Veelvoorkomende valkuilen
Zes faalmodi duiken steeds opnieuw op.
- Kolomnaam-explosie. Kubernetes-specs en GitHub PR-review-threads produceren honderden bladpaden. Oplossing: pre-projecteer met
jqofkubectl jsonpath, of gebruik stringify op zware subbomen terwijl je metadata afvlakt. - Array-lengte komt niet overeen. Rij 1 heeft 3 items, rij 2 heeft 5 items. Geïndexeerde arrays produceren lege cellen in
items.3.skuenitems.4.skuvoor rij 1. Oplossing: schakel over op rij-explosie. - Indexsleutels op de terugweg als strings behandeld. Wanneer CSV-naar-JSON
items.0.skuziet, is de0technisch een string-sleutel. Sommige terug-omzetters reconstrueren{"0": {"sku": "A"}}in plaats van[{"sku": "A"}]. Oplossing: gebruik Stringify voor heen-en-terug. - Sleutels die het scheidingsteken al bevatten. GA4-events hebben sleutels als
event_params.keydie letterlijke punten bevatten; afvlakken met.produceert dubbelzinnige paden. Oplossing: gebruik underscore, of hernoem de problematische sleutels. Zie onze JSON5 en JSONC formatteren voor achtergrond over JSON-formaten met uitgebreide sleutelondersteuning. - Gemengde types op hetzelfde niveau. Sommige rijen hebben
addressals object, andere alsnull. Afvlakken produceert lege cellen waar het object null was. De schema-waarschuwing op onze omzetter markeert het zodat je de downstream-consument kunt verifiëren. - Grote gehele getallen afgekapt door Excel. Een
$oidLong, een Twitter snowflake-ID of een K8sresourceVersionoverschrijdt het veilige bereik van JavaScript (2^53 - 1) en wordt stil afgerond. Excel rendert ze vervolgens als9.00719925474E+15. Oplossing: sla ID’s op als strings in de bron-JSON, zet BOM aan en gebruik de Excel-preset.
FAQ
Wat is de beste manier om geneste JSON af te vlakken naar CSV?
De beste manier om geneste JSON af te vlakken naar CSV hangt af van de downstream-consument. Gebruik puntnotatie voor Excel of Google Sheets. Gebruik rij-explosie wanneer Pandas of BigQuery de data gaat aggregeren. Gebruik Stringify wanneer de CSV verliesvrij terug moet kunnen naar JSON. Stem de strategie af op de volgende lezer.
Hoe zet ik een JSON-array om naar meerdere CSV-rijen?
Zet een JSON-array om naar meerdere CSV-rijen met de explosie-strategie: dupliceer de oudervelden eenmaal per array-element zodat elk element een eigen rij wordt. In Pandas doet pd.json_normalize(data, record_path='items', meta=['order_id']) dat in één aanroep. In SQL produceert UNNEST(items) dezelfde vorm. Oudersleutels herhalen over de geëxplodeerde rijen.
Kan ik CSV heen-en-terug terug naar de oorspronkelijke geneste JSON?
Heen-en-terug van CSV naar de oorspronkelijke geneste JSON werkt alleen met Stringify-modus. Puntnotatie, underscore, geïndexeerde arrays en rij-explosie zijn lossy eenwegprojecties; de omgekeerde omzetter kan de boom niet perfect reconstrueren. Stringify behoudt arrays en objecten als JSON binnen één cel, dus de volledige heen-en-terug is byte-identiek wanneer Infer types aan staat.
Waarom toont Excel mijn afgevlakte JSON als één lange kolom?
Excel toont je afgevlakte JSON als één lange kolom wanneer je in een Europese locale zit (Duitsland, Frankrijk, Italië, Spanje) waar de komma is voorbehouden voor decimalen en Excel puntkomma’s als scheidingsteken verwacht. De Excel-preset op JSON naar CSV Omzetter wisselt met één klik naar ; + CRLF + UTF-8 BOM.
Moet ik puntnotatie of underscore gebruiken voor kolomnamen?
Gebruik puntnotatie wanneer het doel Excel, Google Sheets of Pandas is; punten zijn de standaard van json_normalize en lezen natuurlijk. Gebruik underscore wanneer het doel SQL is: Postgres, BigQuery en Snowflake vereisen quoten rond identifiers met punten, terwijl underscores overal zonder quoten worden geaccepteerd.
Hoe gaat pandas json_normalize om met arrays van objecten?
Pandas json_normalize gaat om met arrays van objecten via de argumenten record_path en meta. pd.json_normalize(data, record_path='items', meta=['order_id']) explodeert items naar één rij per element met order_id herhaald. Voor geneste objecten zonder arrays produceert het eenvoudiger pd.json_normalize(data, sep='_') kolomnamen gescheiden door underscores, zoals customer_address_city. Gebruik max_level= om de diepte te begrenzen op diepe bomen.
Wat is de kolomlimiet bij het afvlakken van diep geneste JSON?
De kolomlimiet bij het afvlakken van diep geneste JSON is 16.384 in Excel en feitelijk onbegrensd in CSV zelf, maar boven de 500 kolommen wordt de uitvoer onhanteerbaar. Kubernetes Pod-specs of GraphQL-responses overschrijden dit gemakkelijk. Gebruik Stringify op de zware subbomen met de JSON naar CSV Omzetter of pre-projecteer met jq of kubectl jsonpath.
Is jq een goede tool om JSON af te vlakken voor CSV-conversie?
Ja, jq is de juiste tool om JSON af te vlakken voor CSV-conversie. Het regelt pre-projectie (map({id, name})), pre-explosie (.[] | {id, item: .items[]}) en vorm-normalisatie in één regel. De jq-pipeline loopt voor de CSV-stap en bepaalt precies welke velden de omzetter bereiken. Zie onze jq spiekbriefje voor patronen.
Conclusie
Vijf kernpunten:
- JSON-naar-CSV is een geometrieprobleem, geen syntaxisprobleem. Een boom past niet in een rooster zonder te kiezen hoe de takken samenvouwen.
- Vijf strategieën dekken het praktische universum (punt, underscore, geïndexeerde arrays, rij-explosie, Stringify). Kies op basis van de consument.
- Stringify is het enige verliesvrije pad. Gebruik het voor pipeline-heen-en-terug.
- Excel-EU en BigQuery hebben presets met een reden. Gebruik ze.
- Echte payloads (mongoexport, Kubernetes-specs, GitHub-responses) hebben meestal eerst een pre-projectiestap met
jqofkubectl jsonpathnodig.
Probeer je eigen payload in de JSON naar CSV Omzetter. Draait lokaal, ondersteunt alle vijf de strategieën, verliesvrij heen-en-terug met Stringify. Geen upload, geen aanmelding, je data verlaat de pagina nooit.