【问题标题】:Json to/from JS objects of certain classesJson 到/来自某些类的 JS 对象
【发布时间】:2018-08-18 21:41:42
【问题描述】:

我有以下 JavaScript 类

class Driver {

   constructor() {
      this._name = null;
      this._car = null;
   }

   setName(name) {
      this._name = name;
   }

   getName() {
      return this._name;
   }

   setCar(car) {
       this._car = car;
   }

   getCar() {
       return this._car;
   }
}

class Car {
   constructor() {
      this._model = null;
   }

   setModel(model) {
      this._model = model;
   }

   getModel(model) {
      return this._model;
   }
}

而我想解决两个问题:

  1. 有以下 json 对象{name:"Boo", car:{model:"Foo"}} 我想用 Car 类的汽车对象获取 Driver 类的驱动程序对象。
  2. 拥有带有 Car 对象的 Driver 对象我想获得像 {name:"Boo", car:{model:"Foo"}} 这样的 json。

是否可以自动执行?我的意思是不用为每个类的每个字段编写代码?

【问题讨论】:

标签: javascript json ecmascript-6


【解决方案1】:

这是绝对可能的,因为 Javascript 为类以及动态类和方法调用提供了完整的反射能力。

JSON 类只是为对象原型提供语法糖,如下所述:(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes)。但是,还有一个新的反射 API 可以提供帮助,尽管它与之前的 Object 方法非常相似 (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect)。

您可以通过这种方式遍历每个属性并递归转换为 json - 这需要遵守对象属性的“_”前缀约定(您可以轻松修改它以处理带前缀和不带前缀的)。如果您希望使用类的 getter 而不是简单地剥离属性,请参阅底部的示例,使用属性作为指南对类进行类似的动态调用:

  function transformUnderscoreProperties(object)
  {
    var returnable = {};
    for (var property in object) {
      if (object.hasOwnProperty(property)) {
        if(property.charAt(0) === '_'){
          let name = property.substr(1); //Property name without _
          if( typeof object[property] === 'object' )
          {
            returnable[name] = transformUnderscoreProperties( object[property] );
          }
          else returnable[name] = object[property];
        }
      }
    }
    return returnable;
  }
  function recursiveObjectStringify( object ) {
    return JSON.stringify( transformUnderscoreProperties( object ) );
  }

如果您想以其他方式执行此操作,可以使用此处的解决方案 (Instantiate a JavaScript Object Using a String to Define the Class Name) 从动态名称构造类,并在此处按原样调用对象上的动态方法 (Javascript dynamically invoke object method from string),但这需要保留对于 setter 方法的骆驼大小写的严格命名约定,并在它们应该转换为的类之后命名 json 的属性:

  function classFromObject( object, className ){
    className = capitalizeFirstLetter( className );
    var returnable = window[className];
    for (var property in object ) {
      if (object.hasOwnProperty(property)) {
        if( typeof object[property] === "object" ){
          returnable["set"+capitalizeFirstLetter(property)]( classFromObject( object[property], property ) ); //Calls "setCar()" on the object returned from the car being made into a class
        }
        else
          returnable["set"+capitalizeFirstLetter(property)]( object[property] ); //Calls "setName()" on the object with the property value.
      }
    }
    return returnable;
  }

  function capitalizeFirstLetter(string) {
    return string.charAt(0).toUpperCase() + string.slice(1);
  }

(以及How do I make the first letter of a string uppercase in JavaScript? 的首字母大写)

编辑: 如果你想使用 getter 来读取属性而不是直接读取属性,这个例子表明,(我已经走到了这一步,不妨展示它的例子):

  function transformUnderscorePropertiesGetters(object)
  {
    var returnable = {};
    for (var property in object) {
      if (object.hasOwnProperty(property)) {
        if(property.charAt(0) === '_'){
          let name = property.substr(1); //Property name without _
          if( typeof object[property] === 'object' )
          {
            returnable[name] = transformUnderscoreProperties( object["get" + capitalizeFirstLetter](name) );
          }
          else returnable[name] = object["get" + capitalizeFirstLetter](name)();
        }
      }
    }
    return returnable;
  }
  function recursiveObjectStringifyGetters( object ) {
    return JSON.stringify( transformUnderscorePropertiesGetters( object ) );
  }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-19
    • 1970-01-01
    • 2012-08-23
    • 2019-03-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多