如何解决如何在 javascript 中将 ES6 类转换为 json 并将 json 解析为该类对象
我有一些如下所示的类,我使用该类创建了一些对象。我想将此对象转换为带有所有嵌套对象的 json。并希望将 json 返回到 A 类的对象。
class A {
constructor(n) {
this.name = n;
this.mapOfA = new Map();
}
}
let a = new A("A");
let b = new A("B");
let c = new A("C");
let d = new A("D");
b.mapOfA.set("D",d);
a.mapOfA.set("B",b);
a.mapOfA.set("C",c);
let jsonString = JSON.stringify(a);
console.log(jsonString); //{"name":"A","mapOfA":{}}
JSON.stringify 只是做一个浅拷贝。我想要深层复制,并且我想像以前一样将 json 字符串转换回 A 类的对象。
解决方法
您可以让类负责自己的序列化和反序列化。然后您可以轻松地将其转换为 JSON,因为该类应该知道其字段以及如何转换它们。那么它应该知道如何将这种转换转回自身的另一个实例:
注意:Stack Overflow 上的可运行代码段会将地图记录为 {}
,即使它有项目。检查浏览器控制台以获得更好的视图。
class A {
constructor(n) {
this.name = n;
this.mapOfA = new Map();
}
toObj() {
//get serialisible fields
const {name,mapOfA} = this;
//convert complex object representation JSON serialisible format
const simpleMapOfA = Object.fromEntries( //convert map to plain object
Array.from(
mapOfA.entries(),//transform the map
([key,value]) => [key,value.toObj()] //convert map values to plain objects
)
);
//return plain object
return {
name,mapOfA: simpleMapOfA
}
}
static from(obj) {
//create a new instance
const instance = new A(obj.name);
//fill the instance `mapOfA` with the data from the input
for (const [key,value] of Object.entries(obj.mapOfA)) {
instance.mapOfA.set(key,A.from(value));
}
return instance;
}
serialise() {
return JSON.stringify(this.toObj());
}
static deserialise(json) {
return A.from(JSON.parse(json));
}
}
let a = new A("A");
let b = new A("B");
let c = new A("C");
let d = new A("D");
b.mapOfA.set("D",d);
a.mapOfA.set("B",b);
a.mapOfA.set("C",c);
let jsonString = a.serialise();
console.log("serialised view:\n",jsonString);
let fooA = A.deserialise(jsonString);
let fooB = fooA.mapOfA.get("B");
let fooC = fooA.mapOfA.get("C");
let fooD = fooB.mapOfA.get("D");
console.log("all four objects still instances of A\n",fooA instanceof A,fooB instanceof A,fooC instanceof A,fooD instanceof A
);
console.log("deserilised objects:\n",fooA,fooB,fooC,fooD);
一般注意事项:
您必须注意只有 JSON 可序列化值。这包括默认值:数字、字符串、布尔值、空值、普通对象和数组。这种方法为 A
和地图的实例添加了only支持。任何其他值都可能丢失或转换。这包括函数、undefined
和 BigInts,以及任何其他自定义对象。
或者,为了将对象本身与序列化/反序列化分开,您可以定义仅使用与您的类相关的数据的函数。您可以利用 the replacer parameter of JSON.stringify()
和 the reviver parameter in JSON.parse()
进行数据的遍历和转换。
class A {
constructor(n) {
this.name = n;
this.mapOfA = new Map();
}
}
function serialiseClassA(instance) {
return JSON.stringify(instance,(key,value) => {
if(value instanceof A) {
//only return serialisible fields
const { name,mapOfA } = value;
//return plain object
return { name,mapOfA };
}
//convert map to plain object
if(value instanceof Map) {
return Object.fromEntries(value);
}
return value;
});
}
function deserialiseClassA(json) {
return JSON.parse(json,value) => {
//it is an object
if (typeof value === "object" && value !== null) {
//it is probably a serialised instance of A
if ("name" in value && "mapOfA" in value) {
//convert value to instance of A
const instance = new A(value.name);
//fill the instance `mapOfA` with the data from the input
for (const [k,v] of value.mapOfA) {
instance.mapOfA.set(k,v);
}
return instance;
}
//it is probably a serialised map
if(key === "mapOfA") {
//convert to a map
return new Map(Object.entries(value));
}
}
return value;
});
}
let a = new A("A");
let b = new A("B");
let c = new A("C");
let d = new A("D");
b.mapOfA.set("D",c);
let jsonString = serialiseClassA(a);
console.log("serialised view:\n",jsonString);
let fooA = deserialiseClassA(jsonString);
let fooB = fooA.mapOfA.get("B");
let fooC = fooA.mapOfA.get("C");
let fooD = fooB.mapOfA.get("D");
console.log("all four objects still instances of A\n",fooD);
一般注意事项:
像上面一样,这只能处理可序列化的值。
此外,反序列化具有更高的风险,因为您会丢失键值对所在位置的上下文。仅依靠对象的属性来确定它是什么对象可能会失败。考虑这个示例,其中映射中有一个键名为 "mapOfA"
和一个 "name"
。这应该反序列化为地图,但因为我们只知道看到普通对象版本,而不知道它在哪里,它被检测为 A
的实例,因此抛出一个错误:
class A {
constructor(n) {
this.name = n;
this.mapOfA = new Map();
}
}
function deserialiseClassA(json) {
return JSON.parse(json,v);
}
return instance;
}
//it is probably a serialised map
if(key === "mapOfA") {
//convert to a map
return new Map(Object.entries(value));
}
}
return value;
});
}
const json = `{
"name": "A","mapOfA": {
"mapOfA": {
"name": "B","mapOfA": {}
},"name": {
"name": "C","mapOfA": {}
}
}
}`;
deserialiseClassA(json); //error
当有正在发生的事情的上下文时进行比较:
class A {
constructor(n) {
this.name = n;
this.mapOfA = new Map();
}
static from(obj) {
//create a new instance
const instance = new A(obj.name);
//fill the instance `mapOfA` with the data from the input
for (const [key,A.from(value));
}
return instance;
}
static deserialise(json) {
return A.from(JSON.parse(json));
}
}
const json = `{
"name": "A","mapOfA": {}
}
}
}`;
const fooA = A.deserialise(json);
const fooB = fooA.mapOfA.get("mapOfA");
const fooC = fooA.mapOfA.get("name");
console.log("all three objects still instances of A\n",);
console.log("deserilised objects:\n",fooC);
这些是大致可以采取的方法:
- 序列化/反序列化逻辑在哪里
- 类内部
- 类外部
- 对数据使用什么转换逻辑:
- 自定义转换然后使用
JSON.stringify()
/JSON.parse()
-
JSON.stringify()
/JSON.parse()
带有替换器/恢复器参数
- 自定义转换然后使用
当然也可以采用一种混合了其中的几种方法。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。