Ontwikkelaars

Wat is JSON? Syntaxregels en veelgemaakte fouten

7 min leestijd

JSON (JavaScript Object Notation) is een tekstformaat voor gestructureerde data: sleutel-waardeparen en geordende lijsten, opgebouwd uit slechts zes waardetypen. Vrijwel elke web-API gebruikt het om data te versturen en te ontvangen, en je komt het net zo vaak tegen in configuratiebestanden, logregels en NoSQL-databases. JSON lijkt oppervlakkig op een JavaScript-objectliteral, maar kent een kleine, strikte set regels: overtreed er één en het hele document wordt onleesbaar voor een parser.

Wat JSON eigenlijk is

Elk JSON-document is opgebouwd uit precies zes waardetypen:

  • String, alleen tussen dubbele aanhalingstekens, zoals "hallo"
  • Number, zoals 42 of 3.14
  • Boolean, ofwel true ofwel false
  • null
  • Object, een ongeordende verzameling sleutel-waardeparen tussen {}
  • Array, een geordende lijst waarden tussen []

Dat is het complete typesysteem. Er is geen datumtype, geen undefined, geen functietype, niets anders. Objecten en arrays mogen zo diep genest zijn als nodig, maar elke waarde op elk niveau moet een van die zes zijn.

De syntaxregels die daarbij horen liggen net zo vast:

  • Objectsleutels moeten dubbel aangehaalde strings zijn. {"name":"Ada"} is geldig; {name:"Ada"} niet.
  • Geen komma’s na het laatste element. De laatste eigenschap in een object en het laatste item in een array mogen geen komma erachter hebben.
  • Geen commentaar, van geen enkele soort, niet // en niet /* */.
  • Strings en sleutels gebruiken uitsluitend dubbele aanhalingstekens. Enkele aanhalingstekens zijn geen geldige JSON-syntax, ook al zijn ze wel geldig in JavaScript.
  • Sleutels mogen nooit onaangehaald blijven, hoe simpel de naam ook is.
  • NaN, Infinity en undefined zijn geen geldige JSON-waarden, ook al bestaan alle drie gewoon in JavaScript.
  • Functies kunnen niet in JSON worden weergegeven. Er is geen manier om gedrag te serialiseren, alleen data.

Overtreed je een van deze regels, dan stopt een JSON-parser en meldt hij een fout in plaats van te raden wat je bedoelde.

JSON versus een JavaScript-objectliteral

De {}- en []-syntax van JSON is geleend van JavaScript object- en arrayliterals, en precies daarom worden de twee zo vaak door elkaar gehaald. Op het scherm lijken ze bijna identiek, maar een JavaScript-objectliteral is op elk punt waar JSON strikt is juist soepeler:

KenmerkJSONJavaScript-objectliteral
Sleutels moeten aangehaald zijnJa, alleen dubbele aanhalingstekensNee, aanhalingstekens optioneel
Komma na laatste element toegestaanNeeJa
Commentaar toegestaanNeeJa
Enkel aangehaalde stringsNeeJa
Functies als waardeNeeJa
undefined als waardeNeeJa

Hier gaat een hoop debugtijd inzitten. Kopieer je een objectliteral zomaar uit een JavaScript-bestand, met onaangehaalde sleutels, een komma na het laatste element en al, naar een plek die JSON verwacht, dan draait dat prima als JavaScript maar loopt het stuk zodra JSON.parse het aanraakt. JSON is geen losjes te schrijven subset van JavaScript-syntax, het is een apart, strenger formaat dat toevallig dezelfde leestekens deelt.

Praktijkvoorbeeld: een echte API-respons minifyen en formatteren

Neem een typisch gebruikersobject zoals een API dat zou teruggeven:

{
  "id": 1,
  "name": "Ada Lovelace",
  "email": "[email protected]",
  "roles": [
    "admin",
    "user"
  ],
  "active": true,
  "meta": null
}

Die pretty-printed versie, met 2-spaties inspringing, telt 145 tekens. Dezelfde data geminificeerd, met elke spatie en regeleinde verwijderd, ziet er zo uit:

{"id":1,"name":"Ada Lovelace","email":"[email protected]","roles":["admin","user"],"active":true,"meta":null}

Dat zijn 107 tekens, ongeveer 35% kleiner, en het verschil zit puur in de witruimte. Geen enkele waarde of sleutel is veranderd, de data is identiek.

Dit is precies waarom API’s JSON geminificeerd over de lijn sturen: op grote schaal levert het schrappen van die 35% aan bytes over miljoenen requests echte besparing op in bandbreedte en latency, en geen enkele client-side code heeft de inspringing nodig om de waarde correct te verwerken. Maar diezelfde geminificeerde string is voor een mens bijna onleesbaar. Ben je een respons aan het debuggen en wil je de nesting, de sleutelnamen en waar een array begint en eindigt kunnen zien, dan formatteer je hem terug naar de ingesprongen versie. Zelfde data, twee verschillende doelen: een voor machines, een voor jou.

Formatteer je eigen JSON

Plak geminificeerde of rommelige JSON hieronder en zie hem meteen netjes ingesprongen terug. Het werkt ook omgekeerd: minify een pretty-printed document voordat je het verstuurt naar een plek waar grootte telt.

JSON Formatter, Beautifier & Validator
Gratis, geen registratie, werkt op elk apparaat.
Open de volledige tool

Veelgemaakte fouten en edge cases

Komma’s na het laatste element. Geef je {"id":1,"name":"Ada",} aan V8 (de engine achter Chrome en Node.js), dan krijg je:

Expected double-quoted property name in JSON at position 21 (line 1 column 22)

Na de komma achter "Ada" volgt niets, en JSON kent geen optionele afsluitende komma. Firefox’ SpiderMonkey-engine formuleert foutmeldingen anders, maar in elke JSON-conforme engine mislukt het parsen op dezelfde manier.

Onaangehaalde sleutels. {id:1} faalt met:

Expected property name or '}' in JSON at position 1 (line 1 column 2)

De parser verwacht direct na { een dubbel aangehaalde string en vindt in plaats daarvan een kale identifier.

Enkel aangehaalde sleutels. {'a':1} levert dezelfde foutklasse op:

Expected property name or '}' in JSON at position 1 (line 1 column 2)

Enkele aanhalingstekens zijn geen geldige manier om een string in JSON te openen, dus de parser behandelt 'a' precies zoals hij een onaangehaalde sleutel zou behandelen: geen geldige eigenschapsnaam.

NaN en undefined als waarde. {"a":NaN} geeft:

Unexpected token 'N', "{"a":NaN}" is not valid JSON

En {"a":undefined} geeft:

Unexpected token 'u', "{"a":undefined}" is not valid JSON

Beide zijn geldig in een JavaScript-objectliteral maar hebben geen representatie in JSON. Kan een waarde in je applicatie NaN of undefined zijn, converteer die dan naar null of een string voordat je serialiseert.

Dubbele sleutels overschrijven stilletjes. {"a":1,"a":2} is syntactisch geldige JSON, zonder enige foutmelding, en levert bij het parsen {"a":2} op. De meeste parsers, waaronder die van JavaScript, houden alleen de laatste voorkomst van een herhaalde sleutel aan en gooien de eerdere stilzwijgend weg. Dit is een sluipende bron van echte bugs: een build-tool die configuratiefragmenten samenvoegt, of een handmatig bewerkt bestand waarin iemand per ongeluk een blok twee keer plakt, kan zo dezelfde sleutel twee keer bevatten, en omdat er geen foutmelding komt merkt niemand het totdat verderop de verkeerde waarde opduikt.

Veelgestelde vragen

Wat is JSON? JSON (JavaScript Object Notation) is een tekstformaat voor gestructureerde data, opgebouwd uit zes waardetypen: strings, numbers, booleans, null, objecten en arrays. Het is het meestgebruikte formaat voor API-requests en -responses, en het duikt ook op in configuratiebestanden en veel databases.

Is JSON hetzelfde als een JavaScript-object? Nee. JSON lijkt op een JavaScript-objectliteral maar is strikter: sleutels moeten dubbel aangehaald zijn, een komma na het laatste element mag niet, commentaar mag niet, en waarden zoals undefined of een functie kunnen helemaal niet worden weergegeven. Een JavaScript-objectliteral staat dat allemaal toe, JSON niets daarvan.

Waarom breekt een overtollige komma mijn JSON? Omdat de grammatica van JSON geen regel kent voor een extra komma na het laatste item in een object of array. Een parser die {"id":1,"name":"Ada",} leest verwacht na de komma nog een eigenschapsnaam en vindt in plaats daarvan de sluitende accolade, precies wat de fout “Expected double-quoted property name in JSON” meldt.

Ondersteunt JSON commentaar? Nee. Er bestaat nergens in de JSON-specificatie syntax voor //- of /* */-commentaar. Wil je een JSON-bestand toch van uitleg voor mensen voorzien, dan grijpen de meeste mensen naar een apart documentatiebestand, een "_comment"-sleutel die als gewone data wordt behandeld, of stappen ze over naar een formaat dat wel commentaar ondersteunt, zoals JSON5 of YAML.

Wat is het verschil tussen formatteren en minifyen? Formatteren (ook wel beautifying of prettifying genoemd) voegt inspringing en regeleindes toe zodat een mens de structuur in één oogopslag kan lezen. Minifyen strippt al die witruimte om de kleinst mogelijke string te produceren. Beide representeren precies dezelfde data, het verschil zit puur in de presentatie, en het is gebruikelijk om tussen de twee te schakelen afhankelijk van of de JSON door een persoon wordt gelezen of over een netwerk wordt verstuurd.

Worden mijn gegevens naar een server gestuurd als ik een online formatter gebruik? Bij de JSON Formatter van pluri.tools niet. Formatteren, minifyen en valideren draaien allemaal met gewoon JSON.parse en JSON.stringify in de JavaScript-engine van je browser. Er komt geen fetch of netwerkverbinding aan te pas, dus de JSON die je plakt verlaat je apparaat nooit.

JSON Formatter, Beautifier & Validator
Probeer het nu zelf met de volledige tool.
Nu proberen