CSV en JSON zijn waarschijnlijk de twee meest voorkomende dataformaten die je als ontwikkelaar zult tegenkomen. CSV-bestanden duiken op in spreadsheet-exports, database-dumps en data science-pijplijnen. JSON is overal op het web — REST-API's, configuratiebestanden, NoSQL-databases. Beide zijn platte tekst, beide zijn door mensen leesbaar en beide doen het werk. Maar ze zijn gebouwd voor verschillende vormen van gegevens, en het verkeerde kiezen zorgt voor echte problemen. Dit artikel bespreekt de kernverschillen, toont concrete voorbeelden van waar elk formaat schittert (en breekt) en geeft je een praktische beslissingsgids voor het kiezen tussen de twee.

Het Kernverschil: Tabellen vs Bomen

CSV — gedefinieerd in RFC 4180 — is een plat, tabulair formaat. Elke rij heeft dezelfde kolommen, elke waarde is een string. Dat is het. Het past perfect op een spreadsheet of een databasetabel: rijen naar beneden, kolommen dwars.

JSON — gespecificeerd in RFC 8259 en beschreven op json.org — is een hiërarchisch formaat. Waarden kunnen objecten, arrays, strings, getallen, booleans of null zijn. Objecten nestelen in objecten, arrays bevatten verschillende vormen. Het past op hoe gegevens werkelijk in code leven — records met relaties, lijsten van verschillende dingen, getypeerde waarden.

Samenvatting in één zin: CSV is een tabel. JSON is een boom. Als je gegevens een tabel zijn, is CSV eenvoudiger en kleiner. Als je gegevens enige nesting hebben, verliest CSV informatie of dwingt je tot pijnlijke omwegen.

Dezelfde Gegevens in Beide Formaten

Hier wordt het verschil concreet. Stel je een productcatalogus voor van een e-commercewinkel. Producten hebben een naam, prijs en of ze op voorraad zijn — eenvoudig. Maar ze hebben ook varianten (maten, kleuren) en attributen (materiaal, gewicht). Laten we bekijken hoe die gegevens eruitzien in beide formaten.

In JSON is dit natuurlijk:

json
[
  {
    "id": "SHOE-001",
    "name": "Trail Runner Pro",
    "price": 129.99,
    "inStock": true,
    "attributes": {
      "material": "mesh",
      "weightGrams": 280
    },
    "variants": [
      { "size": 9,  "color": "black", "sku": "TR-9-BLK",  "qty": 12 },
      { "size": 9,  "color": "white", "sku": "TR-9-WHT",  "qty": 4  },
      { "size": 10, "color": "black", "sku": "TR-10-BLK", "qty": 7  }
    ]
  },
  {
    "id": "SHOE-002",
    "name": "City Walker",
    "price": 89.99,
    "inStock": true,
    "attributes": {
      "material": "leather",
      "weightGrams": 340
    },
    "variants": [
      { "size": 8,  "color": "brown", "sku": "CW-8-BRN",  "qty": 6  },
      { "size": 9,  "color": "brown", "sku": "CW-9-BRN",  "qty": 15 }
    ]
  }
]

Probeer dit nu in een CSV te stoppen. Je hebt twee opties, beide onhandig. Optie één: alles afvlakken en bovenliggende data herhalen voor elke variantrij:

csv
product_id,product_name,price,inStock,material,weightGrams,variant_size,variant_color,sku,qty
SHOE-001,Trail Runner Pro,129.99,true,mesh,280,9,black,TR-9-BLK,12
SHOE-001,Trail Runner Pro,129.99,true,mesh,280,9,white,TR-9-WHT,4
SHOE-001,Trail Runner Pro,129.99,true,mesh,280,10,black,TR-10-BLK,7
SHOE-002,City Walker,89.99,true,leather,340,8,brown,CW-8-BRN,6
SHOE-002,City Walker,89.99,true,leather,340,9,brown,CW-9-BRN,15

De productnaam, prijs en attributen worden herhaald voor elke variant. Dat is gegevensredundantie — niet zo'n groot probleem voor vijf rijen, maar voor een catalogus van 50.000 producten met elk 8 varianten, telt het op. Optie twee: de varianten serialiseren als een JSON-string binnen een CSV-kolom — maar nu embed je JSON in CSV om de beperkingen van CSV te omzeilen, wat een code smell is als je ooit een hebt gezien.

Waar CSV Wint

Ondanks die beperking is CSV echt de betere keuze in verschillende veelvoorkomende scenario's.

  • Spreadsheets en BI-tools. Excel, Google Sheets, Tableau, Looker, Power BI — ze openen allemaal CSV natively met één klik. Geen importwizard, geen te definiëren schema, geen transformatiestap. Als je stakeholders in spreadsheets leven, is CSV de weg van de minste weerstand.
  • Puur platte gegevens. Als je gegevens werkelijk een tabel zijn — analysegebeurtenissen, transactielogboeken, sensormetingen, gebruikersexport — is CSV kleiner en eenvoudiger. Geen herhaalde sleutels, geen haakjes, geen ruis.
  • Database import/export. Elk SQL-database heeft een COPY FROM CSV of gelijkwaardig commando. Het is het standaard uitwisselingsformaat voor bulk data laden en is orden van grootte sneller dan INSERT-statements.
  • pandas en data science. pandas.read_csv() is een van de meest gebruikte functies in Python data werk. Het hele ecosysteem — NumPy, scikit-learn, Polars — behandelt CSV als een eersteklas invoerformaat.
  • Bestandsgrootte voor grote platte tabellen. Zonder sleutelnamen op elke rij is CSV kleiner voor brede tabellen met veel rijen. Een CSV van een miljoen rijen met analysegebeurtenissen verslaat de equivalente JSON-array gemakkelijk.

Waar JSON Wint

  • Geneste en hiërarchische gegevens. Zodra je gegevens enige structuur hebben buiten een platte tabel — geneste objecten, arrays van verschillende vormen, gerelateerde records — verwerkt JSON dit van nature. CSV kan dit niet weergeven zonder informatie te verliezen of redundantie te creëren.
  • Type-behoud. In CSV is alles een string. true, 42, null en "true" zien er allemaal hetzelfde uit. Je moet typen aan de ontvangende kant afleiden, wat leidt tot bugs. JSON heeft native booleans, getallen en null. inStock: true is ondubbelzinnig een boolean — geen giswerk vereist.
  • REST API's en het web. JSON is het native dataformaat van het web. Elke HTTP-clientbibliotheek, elke Fetch API van een browser, elke REST- en GraphQL-API spreekt JSON. CSV via HTTP sturen is mogelijk maar ongebruikelijk — je zou aan beide kanten aangepaste verwerking nodig hebben.
  • NoSQL-databases. MongoDB, DynamoDB, Firestore, Elasticsearch, CouchDB — allemaal gebruiken ze JSON (of een binair superset zoals BSON) als hun native documentformaat. Je schrijft JSON in, je krijgt JSON terug.
  • Configuratiebestanden. package.json, tsconfig.json, manifest.json — toolingconfiguratie heeft zich gestandaardiseerd op JSON omdat het geneste structuren ondersteunt en gemakkelijk programmatisch te genereren en valideren is.
  • Schemavalidatie. JSON Schema laat je de exacte vorm van een document definiëren en gegevens daartegen valideren — typecontroles, verplichte velden, patroonovereenkomst, array-beperkingen. CSV heeft geen equivalente standaard.

Bestandsgrootte: Het Echte Verhaal

De bewering "CSV is kleiner" is waar in één specifiek geval: grote platte tabellen met veel rijen. Neem 100.000 analysegebeurtenissen, elk met acht vaste velden. In CSV verschijnen de veldnamen eenmaal in de header. In JSON verschijnen ze op elk object. Die herhaling telt op — de JSON-array kan 30-50% groter zijn dan de equivalente CSV.

Maar draai het scenario om naar geneste gegevens en de rekening verandert. De afgevlakte CSV van onze schoenencatalogus herhaalt de productnaam, prijs en attributen op elke variantrij. De JSON-versie slaat elk product eenmaal op. Voor diep geneste gegevens met veel herhaalde bovenliggende velden kan JSON feitelijk kleiner zijn.

In de praktijk comprimeren beide formaten zeer goed met gzip als bestandsgrootte een echte zorg is — de repetitieve sleutelnamen in JSON en de herhaalde rijwaarden in CSV comprimeren sterk. Gzipped JSON serveren via HTTP is standaardpraktijk, en het grootteverschil wordt gewoonlijk verwaarloosbaar na compressie.

Toolingvergelijking

Het toolingverhaal voor elk formaat weerspiegelt waar het het meest wordt gebruikt.

CSV-tooling: Excel, Google Sheets en LibreOffice Calc openen het natively. De pandas-bibliotheek maakt CSV de standaard voor gegevensanalyse in Python. Elke relationele database heeft een CSV-import/export-commando. Opdrachtregeltools zoals csvkit en xsv laten je CSV-bestanden filteren, samenvoegen en aggregeren zonder code te schrijven. Het MIME-type is text/csv, geregistreerd bij IANA.

JSON-tooling: elke programmeertaal heeft een ingebouwde of standaardbibliotheek JSON-parser. JSON.parse() in JavaScript, json.loads() in Python, encoding/json in Go, serde_json in Rust. De MDN JSON-referentie is een van de meest bezochte pagina's op MDN. Opdrachtregel: jq is onmisbaar voor het opvragen en transformeren van JSON. IDE's visualiseren het mooi en valideren het automatisch.

Als je werkt met datapijplijnen die beide werelden overspannen — JSON API-antwoorden laden in een data warehouse, of databaserecords exporteren voor een spreadsheet — zul je regelmatig tussen de twee converteren. De CSV naar JSON-converter en de JSON naar CSV-converter doen dat snel. Voor het opruimen van ruwe bestanden voor verwerking zijn de CSV Formatter en JSON Formatter het bookmarken waard.

De Hybride: JSON Lines (NDJSON)

Er is een derde optie die de moeite waard is om te kennen: JSON Lines, ook NDJSON (Newline-Delimited JSON) genoemd. Het idee is eenvoudig — één compleet JSON-object per regel, geen omringende array.

json
{"id":"SHOE-001","name":"Trail Runner Pro","price":129.99,"inStock":true,"variantCount":3}
{"id":"SHOE-002","name":"City Walker","price":89.99,"inStock":true,"variantCount":2}
{"id":"SHOE-003","name":"Summit Hiker","price":159.99,"inStock":false,"variantCount":5}

Dit formaat geeft je het beste van beide werelden voor bepaalde gebruiksscenario's. Net als CSV kun je het regel voor regel streamen en verwerken zonder het hele bestand in het geheugen te laden — cruciaal voor grote logbestanden of datapijplijnuitvoer. Net als JSON kan elke regel een ander schema hebben en behoudt het typen. Je kunt standaard Unix-tools (grep, wc -l, head) gebruiken om ermee te werken, maar ook elke regel door jq sturen voor gestructureerde query's.

NDJSON wordt veel gebruikt voor logaggregatie (het is het standaard uitvoerformaat voor veel gestructureerde loggers), datapijplijnfasen en ML-trainingsdata-exports. Als je een script schrijft dat miljoenen records verwerkt en elk record een JSON-object is, is NDJSON gewoonlijk de juiste keuze boven een gigantische JSON-array — je vermijdt het laden van alles in het geheugen en je kunt gemakkelijk vanaf een controlepunt hervatten.

python
import json

# Process a large NDJSON file without loading it all into memory
with open('products.ndjson', 'r') as f:
    for line in f:
        product = json.loads(line.strip())
        if product['inStock'] and product['price'] < 100:
            print(f"{product['name']} — ${product['price']}")

Beslissingsgids: CSV vs JSON

Hier is de praktische versie. Wanneer je kiest tussen de twee, stel jezelf deze vragen:

  • Zijn je gegevens werkelijk plat (geen nesting, geen arrays)? Als ja, is CSV eenvoudiger. Als nee, JSON.
  • Zal een niet-ontwikkelaar dit bestand gebruiken? Analisten in Excel? Zakelijke gebruikers in Google Sheets? Gebruik CSV.
  • Bedien of verbruik je een HTTP API? Gebruik JSON. Punt.
  • Voer je een bulk database-import of -export uit? Gebruik CSV — elke database ondersteunt het natively.
  • Hebben de gegevens gemengde typen (booleans, getallen, nulls)? Gebruik JSON om type-inferentiebugs aan de ontvangende kant te vermijden.
  • Wordt het bestand rij voor rij verwerkt in een streamingpijplijn? Overweeg NDJSON als tussenvorm.
  • Sla je configuratie op? Gebruik JSON (of YAML als opmerkingen voor je van belang zijn).
  • Moet het schema per record variëren? JSON. CSV dwingt dezelfde kolommen op elke rij af.
De eerlijke standaard: als je iets bouwt voor andere ontwikkelaars of machines om te verbruiken, gebruik JSON. Als je gegevens overhandigt aan een mens die ze in een spreadsheet opent, gebruik CSV. Als je een datapijplijn bouwt die miljoenen gestructureerde records verwerkt, overweeg NDJSON.

Samenvatting

CSV en JSON concurreren niet echt — ze lossen verschillende problemen op. CSV is het juiste gereedschap wanneer je gegevens een tabel zijn en je maximale compatibiliteit wilt met spreadsheet- en databasetools. JSON is het juiste gereedschap wanneer je gegevens structuur, typen of nesting hebben en wanneer je met API's of applicaties communiceert.

De beslissing is gewoonlijk niet moeilijk als je naar de werkelijke vorm van de gegevens kijkt. Platte rijen sensormetingen? CSV. Een API-antwoord met geneste gebruikersprofielen en ingesloten ordergeschiedenissen? JSON. Een streaminglog van gestructureerde gebeurtenissen? NDJSON. Pas het formaat aan op de vorm van de gegevens en de tools aan beide kanten, en je zult zelden fout zitten.