JSON-klassen i JavaScript

JSON-klassen i JavaScript

Denne artikkelen forklarer JSON-klassen i JavaScript.

Vi forklarer JSON-klassen i JavaScript med praktiske eksempler.

YouTube Video

JSON-klassen i JavaScript

JSON-objektet har hovedsakelig to metoder. JSON.stringify() konverterer et objekt til en JSON-streng, og JSON.parse() oppretter et objekt fra en JSON-streng. JSON er et datautvekslingsformat som kun kan representere visse JavaScript-verdier. Funksjoner, undefined, Symbol og sirkulære referanser kan ikke konverteres direkte til JSON.

JSON.stringify()

Her er først et grunnleggende eksempel på å konvertere et objekt til en JSON-streng.

1// Convert a JavaScript object to a JSON string.
2const obj = { name: "Alice", age: 30, active: true };
3const jsonString = JSON.stringify(obj);
4console.log(jsonString); // {"name":"Alice","age":30,"active":true}
  • Denne koden er det mest grunnleggende eksemplet på å konvertere et vanlig objekt til en JSON-streng. JSON.stringify returnerer strengen synkront.

Det andre argumentet til JSON.stringify (replacer)

Ved å spesifisere replacer, det andre argumentet til JSON.stringify, kan du kontrollere konverteringsreglene i detalj. Her er et eksempel der et array brukes for å bare beholde bestemte egenskaper.

1// Use a replacer array to include only specific properties during stringification.
2const user = { id: 1, name: "Bob", password: "secret", role: "admin" };
3const safeJson = JSON.stringify(user, ["id", "name", "role"]);
4console.log(safeJson); // {"id":1,"name":"Bob","role":"admin"}
  • I dette eksemplet utelates password slik at sikker loggføring er mulig. Dette er nyttig når du vil fjerne sensitiv informasjon av sikkerhetsmessige årsaker.

Bruke replacer som en funksjon (for verdikonvertering og filtrering)

Hvis du ønsker mer fleksibilitet, kan du bruke en funksjon for å behandle hver nøkkel og verdi. Nedenfor er et eksempel på å bevare en Date som en ISO-streng.

 1// Use a replacer function to customize serialization.
 2const data = { name: "Carol", joined: new Date("2020-01-01T12:00:00Z") };
 3const jsonCustom = JSON.stringify(data, (key, value) => {
 4  // Convert Date objects to ISO strings explicitly
 5  if (this && this[key] instanceof Date) {
 6    return this[key].toISOString();
 7  }
 8  return value;
 9});
10console.log(jsonCustom); // {"name":"Carol","joined":"2020-01-01T12:00:00.000Z"}
  • I en funksjonell replacer sendes nøkkel og verdi inn, og returverdien brukes i den endelige JSON-strengen. this refererer til foreldreobjektet, så det kan også brukes ved nøstede konverteringer.

Grunnleggende om JSON.parse()

JSON.parse konverterer en JSON-streng tilbake til et objekt. Bruk try/catch for å håndtere ugyldig JSON.

1// Parse a JSON string into an object and handle parsing errors.
2const jsonText = '{"title":"Example","count":42}';
3try {
4  const parsed = JSON.parse(jsonText);
5  console.log(parsed.title); // Example
6} catch (err) {
7  console.error("Invalid JSON:", err.message);
8}
  • Hvis strengen er ugyldig, kastes et unntak, så ha alltid unntakshåndtering ved håndtering av eksterne kilder.

Egendefinert gjenoppretting med reviver (eksempel på gjenoppretting av Date)

Ved å bruke det andre argumentet reviver til JSON.parse, kan du gjenskape verdier. Her er et eksempel på å gjenopprette en lagret datostreng tilbake til et Date-objekt.

 1// Use a reviver to turn ISO date strings back into Date objects.
 2const jsonWithDate = '{"name":"Dana","joined":"2021-06-15T09:00:00.000Z"}';
 3const obj = JSON.parse(jsonWithDate, (key, value) => {
 4  // A simple check for ISO date-like strings
 5  if (typeof value === "string" && /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z$/.test(value)) {
 6    return new Date(value);
 7  }
 8  return value;
 9});
10console.log(obj.joined instanceof Date); // true
  • reviver kalles for hver nøkkel, og returverdien brukes i det endelige objektet. Utfør streng kontroll av datoformat i henhold til din applikasjon.

Pretty-printing og space-argumentet

For å få innrykk for bedre lesbarhet, bruk et tall eller en streng som tredje argument til JSON.stringify.

1// Pretty-print an object with 2-space indentation for readability.
2const config = { host: "localhost", port: 3000, debug: true };
3const pretty = JSON.stringify(config, null, 2);
4console.log(pretty);
5/* {
6  "host": "localhost",
7  "port": 3000,
8  "debug": true
9} */
  • For JSON som skal leses av mennesker, som for logger eller konfigurasjonsfiler, er det nyttig å angi innrykk. Vær imidlertid klar over at dette øker størrelsen.

Slik håndterer du sirkulære referanser

JSON.stringify kaster en TypeError hvis det finnes en sirkulær referanse. En vanlig løsning er å lage en replacer med et seen-sett for å unngå sirkulære referanser.

 1// Safely stringify objects that may contain circular references.
 2function safeStringify(value) {
 3  const seen = new WeakSet();
 4  return JSON.stringify(value, (key, val) => {
 5    if (val && typeof val === "object") {
 6      if (seen.has(val)) return "[Circular]";
 7      seen.add(val);
 8    }
 9    return val;
10  });
11}
12
13const a = { name: "A" };
14a.self = a;
15console.log(safeStringify(a)); // {"name":"A","self":"[Circular]"}
  • Ved å bruke en WeakSet kan du oppdage sirkulære referanser og samtidig unngå minnelekkasje. Ved sirkulær referanse returneres "[Circular]". Det er også mulig å tildele en referanse-ID i stedet for "[Circular]".

Egendefinert serialisering med toJSON-metoden

Hvis du definerer en toJSON-metode på et objekt, bruker JSON.stringify returverdien fra denne. Dette er nyttig hvis du vil innebygge konverteringsregler for hver type.

 1// Define toJSON on a class to customize its JSON representation.
 2class Point {
 3  constructor(x, y) {
 4    this.x = x;
 5    this.y = y;
 6  }
 7  toJSON() {
 8    // This will be used by JSON.stringify
 9    return { x: this.x, y: this.y, type: "Point" };
10  }
11}
12
13const p = new Point(10, 20);
14console.log(JSON.stringify(p)); // {"x":10,"y":20,"type":"Point"}
  • toJSON gjør det mulig å definere serialiseringsregler på objektnivå, noe som ofte er mer lokalt og intuitivt enn å bruke replacer.

Begrensninger og forbehold med JSON

Merkbare eksempler som ikke kan konverteres til JSON er undefined, funksjoner, Symbol, BigInt og sirkulære referanser. Vær også oppmerksom på numerisk presisjon (slik som store heltall og IEEE flyttallavrunding).

 1// Demonstrate values that can't be represented in JSON.
 2const sample = {
 3  a: undefined,
 4  b: function () {},
 5  c: Symbol("s"),
 6  d: 9007199254740993n // BigInt (note: JSON.stringify will throw on BigInt)
 7};
 8// JSON.stringify will throw for BigInt and will drop undefined, functions, symbols in objects.
 9try {
10  console.log(JSON.stringify(sample));
11} catch (err) {
12  console.error("Error during stringify:", err.message);
13}
  • Når du håndterer BigInt, konverter det til en streng eller angi representasjon med egendefinert replacer eller toJSON.

Sikkerhet (når du håndterer ikke-pålitelig JSON)

JSON.parse i seg selv er sikkert og anses som tryggere enn eval, men det er risikabelt å stole blindt på det parse-de objektet og bruke det direkte for eiendomstilgang eller databaseforespørsler. Valider alltid og sjekk at dataene samsvarer med forventet skjema.

1// Parse external JSON and validate expected properties before use.
2const external = '{"username":"eve","role":"user"}';
3const parsed = JSON.parse(external);
4if (typeof parsed.username === "string" && ["user","admin"].includes(parsed.role)) {
5  console.log("Safe to use parsed.username and parsed.role.");
6} else {
7  throw new Error("Invalid payload");
8}
  • For inndata- (skjema-) validering er det robust å bruke biblioteker som ajv.

Ytelseshensyn

Hyppig serialisering og deserialisering av store objekter belaster både CPU og minne. Om nødvendig kan du vurdere å sende kun differanser, bruke binære formater (som MessagePack), eller strømme (behandle data sekvensielt). I nettlesermiljøer kan du noen ganger bruke structuredClone (for kopiering) eller overførbare objekter via postMessage.

Spesifikke råd (kort)

Du kan også vurdere følgende punkter:.

  • For logger: unngå pretty-print og bruk énlinjes JSON for å redusere størrelsen.
  • Objekter som ofte serialiseres bør gjøres lette på forhånd, for eksempel ved å fjerne unødvendige egenskaper.
  • Bruk replacer for å minimere gjennomgang og ekskludere unødvendige egenskaper.

Praktisk eksempel: API-forespørsels- og mottaksflyt

Til slutt – her er en sekvens som viser hvordan man trygt konverterer et objekt til JSON for sending til en server og gjenskaper en dato fra svaret man mottar.

 1// Prepare payload, stringify safely, send via fetch, and revive dates on response.
 2async function sendUserUpdate(url, user) {
 3  // Remove sensitive info before sending
 4  const payload = JSON.stringify(user, (k, v) => (k === "password" ? undefined : v));
 5  const res = await fetch(url, {
 6    method: "POST",
 7    headers: { "Content-Type": "application/json" },
 8    body: payload
 9  });
10
11  const text = await res.text();
12  // Reviver: convert ISO date strings back to Date
13  const data = JSON.parse(text, (key, value) => {
14    if (typeof value === "string" && /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z$/.test(value)) {
15      return new Date(value);
16    }
17    return value;
18  });
19  return data;
20}
  • I dette eksemplet ekskluderes password før sending, og dato gjenopprettes med reviver etter mottak. I faktisk drift må du legge til feilhåndtering og timeout-prosesser.

Sammendrag

Med JSON.stringify() og JSON.parse() kan du konvertere mellom objekter og strenger. Du kan tilpasse konverteringen med replacer og reviver, og hvis du implementerer toJSON i en klasse, kan du også kontrollere hvert objekt individuelt. Sirkulære referanser, BigInt, funksjoner osv. kan ikke håndteres som de er, så disse må behandles på forhånd.

Valider alltid ekstern input, og pass på at sensitiv informasjon ikke er med i logger eller kommunikasjon. Hvis datamengden er stor, bør du unngå pretty-print, vurdere differensiell overføring eller bruke binære formater.

Du kan følge med på artikkelen ovenfor ved å bruke Visual Studio Code på vår YouTube-kanal. Vennligst sjekk ut YouTube-kanalen.

YouTube Video