Při pokusu o objektově orientovaný přístup v Javscriptu narazíte na následující problém:Nativní JSON.stringify()
metoda, která dělá zázraky pro prosté objekty, je pro instance třídy v podstatě nepoužitelná.
Například:
const plainObject = {
hello: 'world',
something: 'else',
nested: {item: {number:10}}
};
JSON.stringify(plainObject);
// Yields the perfect JSON string:
// '{"hello":"world","something":"else","nested":{"item":{"number":10}}}'
class MyFancyClass{
#something;
constructor(){
this.hello = 'world';
this.#something = 'else';
}
get item(){
return {number:10};
}
get nested(){
return {item: this.item}
}
}
const instanceOfMyFancyClass = new MyFancyClass();
JSON.stringify(instanceOfMyFancyClass);
// Yields:
// '{"hello":"world"}'
(To #something
syntaxe je moderní způsob identifikace soukromých vlastností pomocí JavaScriptu, a proto se nezobrazuje v řetězci JSON.)
Pomocí .toJSON()
Když zavoláte vestavěný JavaScript JSON.stringify()
Funkce na objektu hledá toJSON()
funkce na tomto objektu, a pokud taková funkce existuje, zřetězuje výsledek návratové hodnoty této funkce.
To je super praktické, protože vám to umožňuje přidat toJSON()
metodu do vaší třídy a vygenerujte prostý objekt pro stringifikaci.
class MyStringifiableClass {
#something;
constructor(){
this.hello = 'world';
this.#something = 'else';
}
get item(){
return {number:10};
}
get nested(){
return {item: this.item}
}
toJSON(){
return {
hello: this.hello,
something: this.#something,
nested: this.nested
}
}
}
const stringifiableInstance = new MyStringifiableClass();
JSON.stringify(stringifiableInstance);
// '{"hello":"world","something":"else","nested":{"item":{"number":10}}}'
Pomocí .toObject()
a náhrada JSON.stringify
Ale co když nemáte kontrolu nad vnitřnostmi věci, kterou chcete strunizovat, nebo z jiných důvodů nemůžete použít toJSON()
? Nebo co když potřebujete umět skládat stejný objekt různými způsoby?
Přístup, který jsem viděl v několika knihovnách JavaScriptu, je zahrnout metodu .toObject()
který vrací prostou objektovou reprezentaci instance třídy. Název metody pravděpodobně zrcadlí vestavěný .toString()
metoda, kterou mají všechny objekty JavaScriptu. V každém případě s .toObject()
metoda na vašich třídách je skvělá z mnoha důvodů, ale jednu věc nedělá vám pomůže stringification JSON.
To znamená, pokud nevyužijete argument "náhradník" v nativním JavaScriptu JSON.stringify
metoda. Aktualizací náhrady, aby se pokusil použít .toObject()
a poté pomocí této metody ve všech vašich vlastních třídách (a rozšířením vestavěných tříd pro její přidání) můžete stále používat JSON.stringify
smysluplným způsobem na instancích třídy.
class MyStringifiableClass {
#something;
constructor(){
this.hello = 'world';
this.#something = 'else';
}
get item(){
return {number:10};
}
get nested(){
return {item: this.item}
}
toObject(){
return {
hello: this.hello,
something: this.#something,
nested: this.nested
}
}
}
/**
* @param {string} key
* @param {any} value
*/
function jsonStringifyToObjectReplacer(key,value){
if(value && value.toObject){
return value.toObject();
}
return value;
}
const stringifiableInstance = new MyStringifiableClass();
JSON.stringify(stringifiableInstance,jsonStringifyToObjectReplacer);
// And now we're back to where we started:
// '{"hello":"world","something":"else","nested":{"item":{"number":10}}}'
Pro usnadnění zabalte do nativního stringifier svou vlastní funkci a použijte ji v celé své aplikaci:
function stringify(something){
return JSON.stringify(something,jsonStringifyToObjectReplacer);
}
Můžete dokonce kombinovat použití toJSON()
a toObject
(nebo jiné vlastní funkce spolu s vestavěným stringifierem JSON a vlastními funkcemi s vašimi vlastními náhradami pro výstup různých stringovaných verzí instancí vaší třídy v závislosti na kontextu!
Změňte Express.js JSON.stringify
náhradník
Framework Express.js je skvělý pro rychlé nastavení serveru RESTful. Jednou z jeho mnoha skvělých vlastností je způsob, jakým zpracovává odesílání dat zpět klientům:pokud se pokusíte odeslat nějaký objekt JavaScript, Express automaticky tento objekt zřetězí a nastaví Content-Type
záhlaví na "application/json".
// Express server setup
// See {@link https://expressjs.com/en/starter/hello-world.html}
const express = require('express');
const app = express();
app.listen(8080);
app.get('/',(req,res)=>{
res.send({hello:'world'});
// Client recieves '{"hello":"world"}' body
// with content-type header set to "application/json"
});
Ale co když chcete klientovi poslat instanci třídy? Express používá běžný JSON.stringify
metodou na datech, která odesíláte, takže jsme zpátky u původního problému. Naštěstí vám Express umožňuje nastavit jakoukoli náhradu, kterou chcete:
app.set('json replacer',jsonStringifyToObjectReplacer)
A s tím můžete jednoduše res.send(myClassInstance)
v celé vaší aplikaci Express pro všechny třídy, které obsahují .toObject()
metoda.