Udviklere

Konverter JSON til CSV: Escaping, arrays og indlejrede objekter forklaret

8 min læsning

At konvertere JSON til CSV betyder at tage en liste af ensartede objekter og skrive den om til rækker og kolonner adskilt af kommaer. Selve princippet er enkelt, men den regel, der forvirrer flest, er escaping: hvornår en celleværdi skal pakkes ind i anførselstegn, og hvad der sker med et anførselstegn, der allerede findes inde i værdien. Denne artikel gennemgår reglen med et konkret, verificeret eksempel, samt de fejl, folk oftest laver undervejs.

Hvorfor CSV stadig er relevant

JSON er formatet, API’er taler. CSV er formatet, regneark forstår. Så snart data skal ind i Excel, Google Sheets eller en datapipeline, der forventer rækker og kolonner frem for indlejrede nøgler, er CSV stadig den mindste fællesnævner. Det er ikke elegant, det har ingen typer, ingen indlejring og ingen kommentarer, men næsten ethvert værktøj kan importere det uden opsætning. Det gør CSV til det naturlige mellemtrin, når data skal fra et system, der taler JSON (en API, en database-eksport, et logværktøj), til et system, hvor et menneske skal filtrere, sortere eller lave en pivottabel.

Sådan opbygges kolonneoverskrifterne

Kolonnerne bliver til ud fra nøglerne i objekterne, og en vigtig detalje er, hvordan det håndteres, når objekterne ikke har præcis de samme nøgler. Overskrifterne er unionen af samtlige nøgler, der optræder i hele arrayet, ikke kun nøglerne fra det første objekt. Nogle naive konvertere kigger udelukkende på det første objekt og taber stille og roligt en kolonne, hvis et senere objekt har et ekstra felt, det gør dette værktøj ikke.

Tag dette eksempel:

[
  { "id": 1, "name": "Ada" },
  { "id": 2, "name": "Grace", "country": "US" }
]

Fordi det andet objekt introducerer nøglen country, som det første ikke har, bliver den alligevel en kolonne i outputtet, og den række, der mangler værdien, får en tom celle i stedet for en fejl:

id,name,country
1,Ada,
2,Grace,US

Rækkefølgen af kolonner følger den rækkefølge, nøglerne først dukker op i, når arrayet gennemløbes objekt for objekt. Det er derfor country havner sidst her: den optræder først i objekt nummer to.

Det fulde eksempel: escaping i praksis

Her er et mere realistist eksempel med de tre situationer, der udløser escaping-reglen: en værdi med et komma, en værdi med et anførselstegn, og en værdi uden nogen af delene.

[
  { "sku": "A100", "product": "Wireless Mouse, Black", "price": 19.99, "in_stock": true },
  { "sku": "A101", "product": "17\" Laptop Stand", "price": 42.5, "in_stock": false },
  { "sku": "A102", "product": "USB-C Cable", "price": 8.99, "in_stock": true }
]

Konverteret til CSV bliver det til:

sku,product,price,in_stock
A100,"Wireless Mouse, Black",19.99,true
A101,"17"" Laptop Stand",42.5,false
A102,USB-C Cable,8.99,true

Overskrifterne er sku, product, price, in_stock, i den rækkefølge nøglerne først optræder i det første objekt, og fordi alle tre objekter deler præcis de samme fire nøgler, er der ingen tomme celler her.

Gennemgå de tre rækker en for en:

Række 1. Værdien Wireless Mouse, Black indeholder et komma. I CSV er komma feltseparatoren, så hvis værdien fik lov at stå ukvoteret, ville en CSV-læser tro, den var to celler: Wireless Mouse og Black. Reglen løser det ved at pakke hele værdien ind i et par anførselstegn, "Wireless Mouse, Black", hvilket fortæller enhver CSV-parser, at kommaet inde i citationstegnene er en del af værdien, ikke en ny kolonne.

Række 2. Værdien 17" Laptop Stand indeholder selv et bogstaveligt anførselstegn (efter tallet 17, for tommer). Her sker der to ting samtidig: det interne anførselstegn fordobles (" bliver til ""), og hele værdien pakkes alligevel ind i et ydre par anførselstegn, ligesom i række 1. Resultatet bliver "17"" Laptop Stand". Det ser mærkeligt ud ved første øjekast, men det er præcis RFC 4180-reglen: et anførselstegn inde i en kvoteret celle repræsenteres som to anførselstegn i træk, og de yderste to anførselstegn markerer, hvor cellen starter og slutter. Enhver CSV-parser, der følger standarden, læser "" som ét bogstaveligt ", ikke som slutningen på cellen.

Række 3. Værdien USB-C Cable indeholder hverken komma, anførselstegn eller linjeskift, så den passerer uændret igennem uden nogen form for indpakning. Det er langt den mest almindelige situation i virkelige datasæt, men de to første rækker viser, hvorfor reglen skal være der, når den situation en dag opstår.

Prøv det selv

CSV → JSON JSON → CSV
JSON til CSV
Gratis, ingen tilmelding, virker på alle enheder.
Åbn hele værktøjet

Almindelige fejl

Indlejrede objekter bliver til [object Object]. CSV har ingen forestilling om et indlejret objekt, en celle er en enkelt tekstværdi. Når konverteringen støder på en værdi, der selv er et objekt, bliver den skrevet ud som den bogstavelige tekst [object Object], altså ren datatab, ikke en fejlmeddelelse, og det er det farlige ved den: intet advarer dig om, at informationen er væk. Tag dette objekt:

[{ "id": 1, "address": { "city": "Aarhus", "zip": "8000" } }]

Det bliver til:

id,address
1,[object Object]

By-navnet og postnummeret er forsvundet ind i den tekststreng. Løsningen er at flade strukturen ud, før du konverterer, ved at gøre de indlejrede felter til deres egne topniveau-nøgler, for eksempel address_city og address_zip i stedet for et indlejret address-objekt. Så bliver hvert felt sin egen kolonne, og ingen data går tabt.

Arrays bliver til én kommasepareret celle, ikke separate kolonner. En arrayværdi bliver ikke eksploderet til flere kolonner, og den beholder heller ikke sine firkantede parenteser. Elementerne bliver i stedet skrevet sammen med kommaer, uden klammer. Med { "id": 1, "tags": ["red", "blue"] } bliver resultatet:

id,tags
1,"red,blue"

Læg mærke til, at cellen selv indeholder et komma nu (mellem red og blue), og derfor bliver den efterfølgende pakket ind i anførselstegn af den samme escaping-regel, der blev gennemgået ovenfor. Åbner du filen i et regneark, ser du én celle med teksten red,blue, ikke to celler. Hvis du har brug for hvert tag i sin egen kolonne, skal du omstrukturere dataene til faste felter (tag_1, tag_2 og så videre) før konvertering.

Excel og listeseparatoren. Outputtet fra dette værktøj bruger altid komma som skilletegn, der findes ingen semikolon-indstilling. Det er sjældent et problem i engelsksprogede Excel-opsætninger, men dansk Excel bruger som standard komma som decimalseparator, og forventer derfor semikolon som listeseparator ved import af CSV. Dobbeltklikker du en komma-adskilt CSV-fil direkte i dansk Excel, kan hele rækken lande samlet i celle A i stedet for at blive fordelt ud over kolonnerne. Løsningen er enten at bruge Excels funktion “Data > Tekst til kolonner” og eksplicit vælge komma som skilletegn ved import, eller at ændre listeseparatoren i Windows’ regionsindstillinger. Google Sheets har typisk ikke samme problem, da det som regel selv genkender skilletegnet ved import.

At glemme de yderste kantede parenteser. Konverteringen forventer et JSON-array, [ ], selv når du kun har ét enkelt objekt at konvertere. Sender du blot { "id": 1, "name": "Ada" } uden de omsluttende klammer, er input ikke et array, og værktøjet viser en fejl i stedet for at gætte, hvad du mente. Pak altid et enkelt objekt ind som [{ "id": 1, "name": "Ada" }], selv når det kun er én række, du skal have konverteret.

Ofte stillede spørgsmål

Hvilken JSON-struktur kræver værktøjet? Input skal være et JSON-array af flade objekter, altså [{...}, {...}]. Et enkelt objekt uden de omsluttende kantede parenteser bliver afvist, og ugyldig JSON viser en fejlmeddelelse i stedet for at give et forkert resultat.

Hvad sker der, hvis nogle objekter mangler felter, som andre har? Kolonneoverskrifterne bliver unionen af alle nøgler, der forekommer i hele arrayet, ikke kun nøglerne fra det første objekt. Et objekt, der mangler en given nøgle, får blot en tom celle i den kolonne i stedet for at forårsage en fejl eller forskyde de andre kolonner.

Hvorfor bliver mit indlejrede objekt til [object Object] i CSV-filen? Fordi en CSV-celle kun kan indeholde tekst, og standard-tekstrepræsentationen af et JavaScript-objekt er netop den streng. Det er reel datatab, ikke en fejlbesked, så løsningen er at flade strukturen ud selv, før du konverterer, ved at give de indlejrede felter deres egne topniveau-nøgler (for eksempel address_city i stedet for address: { city }).

Hvorfor åbner min CSV-fil forkert i Excel med alt i én kolonne? Fordi output fra dette værktøj altid er kommasepareret, mens dansk Excel som standard forventer semikolon som listeseparator ved import (da komma bruges som decimaltegn). Brug Excels “Data > Tekst til kolonner” og vælg komma som skilletegn manuelt, eller skift listeseparatoren i systemets regionsindstillinger.

Bliver mine data sendt til en server, når jeg bruger værktøjet? Nej. Konverteringen kører udelukkende i din browser via JavaScript. Din JSON forlader aldrig din enhed, og der gemmes ingen kopi af dine data noget sted.

JSON til CSV
Prøv det nu selv med hele værktøjet.
Prøv nu
Relaterede værktøjer