JSON-klassen i JavaScript
Denne artikel forklarer JSON-klassen i JavaScript.
Vi vil forklare JSON-klassen i JavaScript med praktiske eksempler.
YouTube Video
JSON-klassen i JavaScript
JSON-objektet har hovedsageligt to metoder. JSON.stringify() konverterer et objekt til en JSON-streng, og JSON.parse() opretter et objekt ud fra en JSON-streng. JSON er et dataudvekslingsformat, som kun kan repræsentere visse JavaScript-værdier. Funktioner, undefined, Symbol og cirkulære referencer kan ikke direkte konverteres til JSON.
JSON.stringify()
Her er først et grundlæggende eksempel på at 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 kode er det mest grundlæggende eksempel på at konvertere et almindeligt objekt til en JSON-streng.
JSON.stringifyreturnerer strengen synkront.
Det andet argument i JSON.stringify (replacer)
Ved at angive replacer, som er det andet argument i JSON.stringify, kan du finjustere konverteringsreglerne. Her er et eksempel, hvor man bruger et array til kun at beholde bestemte egenskaber.
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 eksempel udelades
passwordfor at muliggøre sikker logoutput. Dette er nyttigt, når du vil fjerne følsomme oplysninger af sikkerhedsmæssige årsager.
Brug af replacer som en funktion (til værdikonvertering og filtrering)
Hvis du ønsker mere fleksibilitet, kan du angive en funktion til at bearbejde hver nøgle og værdi. Nedenfor er et eksempel på at gemme 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 funktionstype
replacervideregives nøgle og værdi, og den returnerede værdi bruges i den endelige JSON.thisrefererer til forældre-objektet, så det kan også bruges til indlejrede konverteringer.
Det grundlæggende om JSON.parse()
JSON.parse konverterer en JSON-streng tilbage til et objekt. Indpak det med try/catch, så du kan 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, vil der blive kastet en undtagelse, så husk altid at inkludere undtagelseshåndtering ved eksterne kilder.
Brugerdefineret gendannelse med reviver (eksempel på gendannelse af Date)
Ved at bruge det andet argument, reviver, i JSON.parse kan du udføre værdigengivelse. Her er et eksempel på at konvertere en gemt streng-dato tilbage 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
reviverbliver kaldt for hver nøgle, og den returnerede værdi bruges i det endelige objekt. Foretag venligst streng datotjek i henhold til din applikation.
Pæn formatering og argumentet space
For at udskrive med indrykning for læsbarhed skal du angive et tal eller en streng som det 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, der skal læses af mennesker, såsom logs eller uddata fra konfigurationsfiler, er det nyttigt at angive indrykning. Vær dog opmærksom på, at dette øger størrelsen.
Sådan håndteres cirkulære referencer
JSON.stringify kaster en TypeError, hvis der er en cirkulær reference. En almindelig løsning er at oprette en replacer, der bruger et seen-sæt for at undgå cirkulære referencer.
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 at bruge en
WeakSetkan du opdage cirkulære referencer uden at forårsage hukommelseslækager. I tilfælde af en cirkulær reference returneres"[Circular]". Det er også muligt at tildele et reference-ID i stedet for"[Circular]".
Brugerdefineret serialisering med toJSON-metoden
Hvis du definerer en toJSON-metode på et objekt, bruger JSON.stringify dens returværdi. Dette er nyttigt, når du vil indlejre 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"}
toJSONgør det muligt at definere serialiseringsregler på objektniveau, hvilket gør det mere lokalt og intuitivt end at brugereplacer.
Begrænsninger og forbehold ved JSON
Bemærkelsesværdige eksempler, der ikke kan konverteres til JSON, er undefined, funktioner, Symbol, BigInt samt cirkulære referencer. Vær også opmærksom på numerisk præcision (for eksempel store heltal og IEEE-flydende punktafrunding).
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, skal du konvertere det til en streng eller definere dets repræsentation ved hjælp af en brugerdefineretreplacerellertoJSON.
Sikkerhed (ved håndtering af utroværdig JSON)
JSON.parse i sig selv er sikker og anses for mere sikker end eval, men det er farligt at stole på det analyserede objekt og bruge det direkte til at tilgå egenskaber eller databaseforespørgsler. Valider altid, og tjek at dataene stemmer overens med det forventede skema.
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 indtastningsvalidering (skemavalidering) er det robust at bruge biblioteker som
ajv.
Ydelsesmæssige overvejelser
Hyppig serialisering og deserialisering af store objekter belaster CPU'en og hukommelsen. Om nødvendigt kan du overveje kun at sende forskellene, bruge binære formater (som MessagePack), eller streame (behandle data sekventielt). I browsermiljøer kan du i visse tilfælde benytte structuredClone (til kopiering) eller overførbare objekter i postMessage.
Specifik rådgivning (kort)
Du kan også overveje følgende punkter:.
- Undgå pæn formatering i logs, og brug linje-JSON for at reducere størrelsen.
- Objekter, der ofte serialiseres, bør gøres lette på forhånd, f.eks. ved at fjerne unødvendige egenskaber.
- Brug
replacertil at minimere gennemløb og udelukke unødvendige egenskaber.
Praktisk eksempel: Send/modtag-flow for API-anmodning
Til sidst er her en sekvens, der viser, hvordan man sikkert konverterer et objekt til JSON ved afsendelse til en server og gendanner en dato fra det modtagne svar.
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 eksempel udelades
passwordfør afsendelse, og dato bliver gendannet afreviverved modtagelse. I virkelig drift skal du tilføje fejlhåndtering og timeout-behandling.
Sammendrag
Ved hjælp af JSON.stringify() og JSON.parse() kan du konvertere mellem objekter og strenge. Du kan tilpasse konverteringsprocessen ved hjælp af replacer og reviver, og hvis du implementerer toJSON i en klasse, kan du også styre hvert objekt individuelt. Cirkulære referencer, BigInt, funktioner osv. kan ikke håndteres som de er, så du skal behandle dem på forhånd.
Valider altid ekstern input, og sørg for, at følsomme oplysninger ikke medtages i logs eller kommunikation. Hvis datamængden er stor, er det effektivt at undgå pæn formatering, overveje differentiel transmission eller bruge binære formater.
Du kan følge med i ovenstående artikel ved hjælp af Visual Studio Code på vores YouTube-kanal. Husk også at tjekke YouTube-kanalen.