将ES6类对象序列化为JSON

时间:2016-10-23 09:49:48

标签: javascript json ecmascript-6 es6-class

class MyClass {
  constructor() {
    this.foo = 3
  }
}

var myClass = new MyClass()

我想将myClass对象序列化为json。

我能想到的一个简单方法是,因为每个成员实际上都是javascript对象(数组等)。我想我可以维护一个变量来保存成员变量。

this.prop.foo = this.foo等等。

我希望为类对象找到一个toJSON/fromJSON库,因为我将它们与swift / java等其他语言一起使用,但是找不到javascript。

也许类构造太新了,或者我所要求的可以在没有库的情况下以某种方式轻松实现。

6 个答案:

答案 0 :(得分:6)

与想要在JS中进行字符串化的任何其他对象一样,您可以使用JSON.stringify

JSON.stringify(yourObject);

class MyClass {
  constructor() {
    this.foo = 3
  }
}

var myClass = new MyClass()

console.log(JSON.stringify(myClass));

另外值得注意的是,您可以通过为toJSON method自定义stringify序列化对象的方式。用于在生成的JSON字符串中表示对象的值将是在该对象上调用toJSON方法的结果。

答案 1 :(得分:5)

我知道这个问题很老但是我一直在盯着我看,直到我写了一个紧凑的真实,“安全”的解决方案。

反序列化返回仍然附加有工作方法的对象。

您唯一需要做的就是在序列化程序的构造函数中注册要使用的类。

class Serializer{
    constructor(types){this.types = types;}
    serialize(object) {
        let idx = this.types.findIndex((e)=> {return e.name == object.constructor.name});
        if (idx == -1) throw "type  '" + object.constructor.name + "' not initialized";
        return JSON.stringify([idx, Object.entries(object)]);
    }
    deserialize(jstring) {
        let array = JSON.parse(jstring);
        let object = new this.types[array[0]]();
        array[1].map(e=>{object[e[0]] = e[1];});
        return object;
    }
}

class MyClass {
    constructor(foo) {this.foo = foo;}
    getFoo(){return this.foo;}
}

var serializer = new Serializer([MyClass]);

console.log(serializer.serialize(new MyClass(42)));
//[0,[["foo",42]]]

console.log(serializer.deserialize('[0,[["foo",42]]]').getFoo());
//42

以上内容足以让您前进,但可以找到更多详细信息和缩小版本here

答案 2 :(得分:1)

我遇到了这个库,它可以对复杂对象进行序列化和反序列化:

https://github.com/typestack/class-transformer

它至少有两种方法:

plainToClass() -> json obj to class
classToPlain() -> class to json obj

为寻求此类解决方案的人提供安全时间

答案 3 :(得分:0)

您需要能够递归地重新初始化对象。拥有无参数的构造函数不是必不可少的,您可以不用一个就可以逃脱。

这是我执行深度复制的方式:

class Serializer
{
  constructor(types){
    this.types = types;
  }

  markRecursive(object)
  {
    // anoint each object with a type index
    let idx = this.types.findIndex(t => {
      return t.name === object.constructor.name;
    });
    if (idx !== -1)
    {
      object['typeIndex'] = idx;

      for (let key in object)
      {
        if (object.hasOwnProperty(key))
          this.markRecursive(object[key]);
      }
    }
  }

  reconstructRecursive(object)
  {
    if (object.hasOwnProperty('typeIndex'))
    {
      let type = this.types[object.typeIndex];
      let obj = new type();
      for (let key in object)
      {
        if (object.hasOwnProperty(key) && object[key] != null) {
          obj[key] = this.reconstructRecursive(object[key]);
        }
      }
      delete obj.typeIndex;
      return obj;
    }
    return object;
  }

  clone(object)
  {
    this.markRecursive(object);
    let copy = JSON.parse(JSON.stringify(object));
    return this.reconstructRecursive(copy);
  }
}

这个想法很简单:序列化时,每个已知类型的成员(一种this.types中的类型)都会被一个名为typeIndex的成员涂膏。反序列化后,我们递归初始化每个具有typeIndex的子结构,然后将其删除以避免污染该结构。

答案 4 :(得分:0)

我制作了一个模块esserializer来解决此问题。它是一个实用程序,用于序列化JavaScript类实例,并将“序列化文本”反序列化为实例对象,同时保留所有Class / Property / Method等。

要序列化实例,只需调用serialize()方法:

const ESSerializer = require('esserializer');
let serializedString = ESSerializer.serialize(anObject);

serialize()的内部机制是:将实例的属性及其类名信息递归保存到字符串中。

要从字符串反序列化,只需调用deserialize()方法,并将所有涉及的类作为参数传递即可。

const ESSerializer = require('esserializer');
const ClassA = require('./ClassA');
const ClassB = require('./ClassB');
const ClassC = require('./ClassC');

let deserializedObj = ESSerializer.deserialize(serializedString, [ClassA, ClassB, ClassC]);

deserialize()的内部机制是:以递归方式手动将对象及其原型信息组成。

答案 5 :(得分:0)

如果您不介意将类定义传递给解码,这很容易。

import nrrd