Vad är JSON? Syntaxregler och hur du rättar vanliga fel
JSON (JavaScript Object Notation) är ett textformat för strukturerad data uppbyggt av nyckel-värde-par och ordnade listor, med bara sex möjliga värdetyper. Det är formatet nästan alla webb-API:er använder för att skicka och ta emot data, och det dyker lika ofta upp i konfigurationsfiler, loggrader och NoSQL-databaser. JSON liknar ett JavaScript-objektlitteral på ytan, men har ett litet, strikt regelverk, och bryter du mot en enda regel går hela dokumentet inte att tolka.
Vad JSON egentligen är
Varje JSON-dokument byggs av exakt sex värdetyper:
- Sträng, endast med dubbla citattecken, till exempel
"hej" - Tal, till exempel
42eller3.14 - Boolean, antingen
trueellerfalse null- Objekt, en oordnad samling nyckel-värde-par inom
{} - Array, en ordnad lista med värden inom
[]
Det är hela typsystemet. Det finns ingen datumtyp, inget undefined, ingen funktionstyp, inget annat. Objekt och arrayer kan nästlas i varandra hur djupt som helst, men varje värde på varje nivå måste vara en av de sex typerna.
Syntaxreglerna som hör till är lika fasta:
- Nycklar i ett objekt måste vara strängar med dubbla citattecken.
`{"namn":"Ada"}`är giltigt,`{namn:"Ada"}`är det inte. - Inga avslutande kommatecken. Sista egenskapen i ett objekt och sista elementet i en array får inte ha komma efter sig.
- Inga kommentarer, varken
//eller/* */. - Strängar och nycklar använder enbart dubbla citattecken. Enkla citattecken är giltig JavaScript men ogiltig JSON.
- Nycklar kan aldrig lämnas ociterade, oavsett hur enkelt namnet är.
NaN,Infinityochundefinedär inga giltiga JSON-värden, trots att alla tre är giltiga i JavaScript.- Funktioner går inte att representera i JSON över huvud taget. Ett värde är antingen en av de sex typerna, eller så finns det inte.
JSON jämfört med ett objektlitteral i JavaScript
Det här är precis där de flesta felen uppstår: ett JavaScript-objekt och ett JSON-dokument ser nästan likadana ut på skärmen, men det ena tillåter en hel del som det andra vägrar. Du skriver ett objektlitteral i din editor, det fungerar perfekt i koden, och sedan kastar JSON.parse fel så fort samma text sparas som en .json-fil eller skickas som request-body.
| Funktion | JSON | JavaScript-objektlitteral |
|---|---|---|
| Nycklar måste citeras | Ja, endast dubbla citattecken | Nej, citattecken är valfritt |
| Avslutande komma tillåtet | Nej | Ja |
| Kommentarer tillåtna | Nej | Ja |
| Enkelciterade strängar | Nej | Ja |
| Funktioner som värden | Nej | Ja |
undefined som värde | Nej | Ja |
Anledningen till att det här spökar så ofta är att en JavaScript-motor och en JSON-parser tolkar samma tecken helt olika. {namn:"Ada", roll:'admin',} kör felfritt som objektlitteral rakt i din kod, komplett med ociterad nyckel, enkla citattecken och ett avslutande komma. Klistra in exakt samma text i JSON.parse och samtliga tre saker stoppar tolkningen. JSON är med andra ord en delmängd av det JavaScript-syntaxen tillåter, aldrig en utökning av den.
Praktiskt exempel: minifiera och formatera ett riktigt API-svar
Så här kan ett vanligt API-svar se ut i sin mest kompakta form, minifierat utan ett enda extra mellanslag, exakt 107 tecken:
{"id":1,"name":"Ada Lovelace","email":"[email protected]","roles":["admin","user"],"active":true,"meta":null}
Samma objekt, formaterat med 2 mellanslags indrag, är exakt 145 tecken:
{
"id": 1,
"name": "Ada Lovelace",
"email": "[email protected]",
"roles": [
"admin",
"user"
],
"active": true,
"meta": null
}
Skillnaden på 38 tecken är rent mellanrum och radbrytningar, ungefär 35 procent extra vikt jämfört med den minifierade versionen, utan att en enda bit faktisk data tillkommer. Det förklarar varför ett API nästan alltid svarar med den minifierade formen: färre byte över nätverket, snabbare parsning, ingen mänsklig läsare inblandad i det steget. Men samma minifierade sträng är plågsam att felsöka för ett mänskligt öga, ett enda saknat komma är omöjligt att hitta på en enda rad med hundra tecken. Därför formaterar utvecklare tillbaka den till den läsbara formen så fort de behöver inspektera den, till exempel när ett API returnerar ett oväntat fält eller ett fel någonstans djupt nere i en nästlad struktur.
Formatera din egen JSON
Klistra in din egen JSON nedan för att se den formaterad, validerad och minifierad direkt i webbläsaren.
Vanliga misstag och specialfall
Avslutande komma. Skriver du `{"id":1,"name":"Ada",}` med ett komma efter det sista fältet stoppar V8 (motorn bakom Chrome och Node.js, och samma motor som kör verktygets JSON.parse lokalt i de flesta besökares webbläsare) parsningen med felmeddelandet Expected double-quoted property name in JSON at position 21 (line 1 column 22). Felet pekar på positionen direkt efter kommat, där parsern förväntade sig antingen en ny citerad nyckel eller en avslutande } och fick varken.
Ociterad nyckel. `{id:1}` ger Expected property name or '}' in JSON at position 1 (line 1 column 2). Parsern kräver ett citattecken direkt efter den öppnande klammern, och en bar bokstav duger inte.
Enkelciterad nyckel. `{'a':1}` ger samma felklass: Expected property name or '}' in JSON at position 1 (line 1 column 2). Ur parserns perspektiv är en enkel apostrof lika ogiltig som en helt ociterad nyckel, den känner bara igen dubbla citattecken som en giltig nyckelstart.
NaN som värde. `{"a":NaN}` ger Unexpected token 'N', "{"a":NaN}" is not valid JSON. NaN är ett giltigt JavaScript-värde men existerar inte i JSON:s typsystem, parsern ser bokstaven N där den förväntade sig en siffra, ett citattecken eller ett av nyckelorden true, false eller null.
undefined som värde. `{"a":undefined}` ger Unexpected token 'u', "{"a":undefined}" is not valid JSON. Samma logik som ovan: undefined finns i JavaScript men har ingen motsvarighet i JSON, ett fält som ska sakna värde uttrycks i JSON i stället genom att helt utelämna nyckeln eller sätta värdet till null.
Den exakta formuleringen på de här felmeddelandena kan skilja sig mellan webbläsare, Firefox SpiderMonkey-motor fraserar felen annorlunda än V8, men parsningen misslyckas på samma ställe och av samma anledning oavsett motor.
Dubbletter av samma nyckel. Det här är det lömska fallet, för det kastar inget fel alls. `{"a":1,"a":2}` är fullt giltig JSON-syntax och parsas utan klagomål till `{"a":2}`. De flesta parsrar, inklusive JavaScripts egen, behåller tyst bara den sista förekomsten och kastar bort den första. I praktiken är det här en klassisk källa till svårupptäckta buggar: ett byggverktyg som slår ihop två konfigurationsfiler, eller en handredigerad JSON-fil där någon råkat klistra in samma fält två gånger, ger aldrig ett felmeddelande, bara ett tyst fel värde som ingen märker förrän långt senare.
Vanliga frågor
Vad är JSON?
JSON (JavaScript Object Notation) är ett textbaserat format för strukturerad data, uppbyggt av sex värdetyper: sträng, tal, boolean, null, objekt och array. Det används som utbytesformat mellan server och klient i så gott som alla moderna webb-API:er, och ofta även i konfigurationsfiler och loggar.
Är JSON samma sak som ett JavaScript-objekt?
Nej, även om de ser nästan likadana ut. JSON är en strikt delmängd av vad JavaScript-syntaxen tillåter: nycklar måste ha dubbla citattecken, avslutande kommatecken är förbjudna, kommentarer är förbjudna, och funktioner eller undefined kan inte förekomma som värden. Ett JavaScript-objektlitteral tillåter alla dessa saker, ett JSON-dokument tillåter inget av dem.
Varför gör ett extra kommatecken att min JSON går sönder? Ett avslutande komma efter det sista fältet eller elementet är inte tillåtet i JSON-specifikationen, till skillnad från i JavaScript där det är helt ofarligt. Parsern förväntar sig antingen ett nytt fält eller en avslutande klammer direkt efter ett komma, och när den hittar varken det ena eller det andra avbryts tolkningen med ett felmeddelande som pekar på exakt den positionen.
Stödjer JSON kommentarer?
Nej, inga kommentarer av något slag, varken //-stil eller /* */-block. Det är en medveten begränsning i formatet: JSON är tänkt att vara ett rent dataformat för maskiner att tolka, inte en konfigurationsspråk med förklarande text inbakad.
Vad är skillnaden mellan att formatera och minifiera JSON? Formatering lägger till indrag och radbrytningar så att strukturen blir läsbar för ett mänskligt öga, vilket ökar filstorleken utan att ändra datan. Minifiering gör det motsatta: den tar bort allt onödigt mellanrum för att göra filen så liten som möjligt, vilket är den form API:er oftast skickar över nätverket eftersom färre byte betyder snabbare överföring.
Skickas mina data till en server när jag använder verktyget ovan?
Nej. Formateraren kör JSON.parse och JSON.stringify helt i din egen webbläsare med vanlig JavaScript, det görs inget nätverksanrop alls. Den JSON du klistrar in lämnar aldrig din enhet.