Hopp til innhold
NorscodeNorscode

Lese og skrive JSON

EksempelAv Norscode-prosjektet

Bygg et JSON-svar i en webtjeneste — og forstå hvorfor escaping av brukerdata ikke er valgfritt.

JSON ligger i standardbiblioteket, så du slipper en avhengighet for noe så vanlig som å svare på et API-kall.

bruk std.web som web
bruk std.json som json

funksjon api_status(ctx: ordbok_tekst) -> ordbok_tekst {
    web.route("GET /api/status")
    la svar = "{" + json.streng("status") + ":" + json.streng("ok") + "}"
    returner web.response_builder(200, {"content-type": "application/json"}, svar)
}

funksjon start() -> heltall {
    skriv("API-et er klart")
    returner 0
}

Hva som skjer her

Innholdstypen application/json er ikke pynt. Den forteller klienten hvordan svaret skal tolkes, og mange klientbiblioteker nekter å parse et svar som er merket som ren tekst. Setter du feil type, får du feilsøkingsrunder som handler om alt annet enn den egentlige feilen.

Legg merke til at også nøkkelen går gjennom json.streng. Det virker overdrevent når nøkkelen er en fast tekst du selv har skrevet, men vanen er verdt å ha: den dagen nøkkelen kommer fra en variabel, er koden allerede riktig.

Escaping er ikke valgfritt

Dette er den viktigste delen av oppskriften. Skal en verdi fra brukeren inn i JSON, må den escapes.

// FEIL: navnet kan inneholde anførselstegn og bryte ut av strengen
la farlig = "{" + json.streng("navn") + ":" + navn + "}"

// RIKTIG: la biblioteket escape verdien
la trygg = "{" + json.streng("navn") + ":" + json.streng(navn) + "}"

Tenk gjennom hva som skjer i den første varianten hvis noen registrerer seg med et navn som inneholder et anførselstegn. Strengen avsluttes midt inne, og resten av navnet blir tolket som JSON-struktur. I beste fall får du et ugyldig svar. I verste fall bestemmer den som skrev navnet hvordan resten av dokumentet ser ut — og hvis mottakeren stoler på feltene, har du gitt bort kontrollen.

Det som gjør denne feilen farlig, er at den ikke merkes i testing. Alle navnene du selv prøver med fungerer fint. Feilen dukker først opp den dagen ekte brukerdata treffer koden.

Samme regel, tre steder

Regelen er den samme for HTML, SQL og JSON: bygg aldri strukturert tekst ved å lime sammen brukerdata. Bruk escape-funksjonen for formatet du skriver til.

FormatFunksjonHva den beskytter mot
HTMLnf.html_escapeat inndata kjøres som skript i nettleseren
SQLnf.sql_textat inndata endrer hva spørringen gjør
JSONjson.strengat inndata bryter ut og endrer dokumentstrukturen

Tre ulike funksjoner fordi de tre formatene har ulike spesialtegn. Å bruke feil av dem er nesten like ille som å ikke bruke noen.

Å lese JSON du har fått inn

Går du andre veien og tar imot JSON, gjelder en regel til: stol aldri på at strukturen er slik du forventer. Et felt kan mangle, ha feil type, eller inneholde noe helt annet enn det avsenderen lovet. Sjekk før du bruker, og bestem hva som skal skje når noe ikke stemmer — før feilen oppstår, ikke etterpå.

Les også

Tilbake til oversikten