如何在 javascript 中将 ES6 类转换为 json 并将 json 解析为该类对象

如何解决如何在 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 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)> insert overwrite table dwd_trade_cart_add_inc > select data.id, > data.user_id, > data.course_id, > date_format(
错误1 hive (edu)> insert into huanhuan values(1,'haoge'); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive> show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 <configuration> <property> <name>yarn.nodemanager.res