我从远程REST服务器读取了一个JSON对象。这个JSON对象具有typescript类的所有属性(根据设计)。我如何转换收到的JSON对象的类型var?

我不想填充一个typescript变量(即有一个构造函数,以这个JSON对象)。它很大,在子对象和属性之间复制所有内容将花费大量时间。

更新:你可以将它转换为typescript接口!


当前回答

TLDR:一个班轮

// This assumes your constructor method will assign properties from the arg.
.map((instanceData: MyClass) => new MyClass(instanceData));

详细回答

我不推荐Object。赋值方法,因为它会不恰当地用类本身中没有声明的不相关属性(以及定义的闭包)丢弃类实例。

在您试图反序列化的类中,我将确保您想要反序列化的任何属性都已定义(null,空数组等)。通过用初始值定义属性,在尝试迭代要赋值的类成员时暴露了它们的可见性(请参阅下面的反序列化方法)。

export class Person {
  public name: string = null;
  public favoriteSites: string[] = [];

  private age: number = null;
  private id: number = null;
  private active: boolean;

  constructor(instanceData?: Person) {
    if (instanceData) {
      this.deserialize(instanceData);
    }
  }

  private deserialize(instanceData: Person) {
    // Note this.active will not be listed in keys since it's declared, but not defined
    const keys = Object.keys(this);

    for (const key of keys) {
      if (instanceData.hasOwnProperty(key)) {
        this[key] = instanceData[key];
      }
    }
  }
}

在上面的例子中,我简单地创建了一个反序列化方法。在实际示例中,我将它集中在可重用基类或服务方法中。

这里是如何利用这在一些像http响应…

this.http.get(ENDPOINT_URL)
  .map(res => res.json())
  .map((resp: Person) => new Person(resp) ) );

如果tslint/ide抱怨参数类型不兼容,只需使用尖括号<YourClassName>将参数转换为相同的类型,例如:

const person = new Person(<Person> { name: 'John', age: 35, id: 1 });

如果你有特定类型的类成员(又名:另一个类的实例),那么你可以通过getter/setter方法将它们强制转换为类型化实例。

export class Person {
  private _acct: UserAcct = null;
  private _tasks: Task[] = [];

  // ctor & deserialize methods...

  public get acct(): UserAcct {
    return this.acct;
  }
  public set acct(acctData: UserAcct) {
    this._acct = new UserAcct(acctData);
  }

  public get tasks(): Task[] {
    return this._tasks;
  }

  public set tasks(taskData: Task[]) {
    this._tasks = taskData.map(task => new Task(task));
  }
}

上面的例子将把acct和任务列表反序列化到它们各自的类实例中。

其他回答

TLDR:一个班轮

// This assumes your constructor method will assign properties from the arg.
.map((instanceData: MyClass) => new MyClass(instanceData));

详细回答

我不推荐Object。赋值方法,因为它会不恰当地用类本身中没有声明的不相关属性(以及定义的闭包)丢弃类实例。

在您试图反序列化的类中,我将确保您想要反序列化的任何属性都已定义(null,空数组等)。通过用初始值定义属性,在尝试迭代要赋值的类成员时暴露了它们的可见性(请参阅下面的反序列化方法)。

export class Person {
  public name: string = null;
  public favoriteSites: string[] = [];

  private age: number = null;
  private id: number = null;
  private active: boolean;

  constructor(instanceData?: Person) {
    if (instanceData) {
      this.deserialize(instanceData);
    }
  }

  private deserialize(instanceData: Person) {
    // Note this.active will not be listed in keys since it's declared, but not defined
    const keys = Object.keys(this);

    for (const key of keys) {
      if (instanceData.hasOwnProperty(key)) {
        this[key] = instanceData[key];
      }
    }
  }
}

在上面的例子中,我简单地创建了一个反序列化方法。在实际示例中,我将它集中在可重用基类或服务方法中。

这里是如何利用这在一些像http响应…

this.http.get(ENDPOINT_URL)
  .map(res => res.json())
  .map((resp: Person) => new Person(resp) ) );

如果tslint/ide抱怨参数类型不兼容,只需使用尖括号<YourClassName>将参数转换为相同的类型,例如:

const person = new Person(<Person> { name: 'John', age: 35, id: 1 });

如果你有特定类型的类成员(又名:另一个类的实例),那么你可以通过getter/setter方法将它们强制转换为类型化实例。

export class Person {
  private _acct: UserAcct = null;
  private _tasks: Task[] = [];

  // ctor & deserialize methods...

  public get acct(): UserAcct {
    return this.acct;
  }
  public set acct(acctData: UserAcct) {
    this._acct = new UserAcct(acctData);
  }

  public get tasks(): Task[] {
    return this._tasks;
  }

  public set tasks(taskData: Task[]) {
    this._tasks = taskData.map(task => new Task(task));
  }
}

上面的例子将把acct和任务列表反序列化到它们各自的类实例中。

在后期TS,你可以这样做:

const isMyInterface = (val: any): val is MyInterface => {
  if (!val) { return false; }
  if (!val.myProp) { return false; }
  return true;
};

而用户是这样的:

if (isMyInterface(data)) {
 // now data will be type of MyInterface
}

我认为json2typescript是一个不错的选择 https://www.npmjs.com/package/json2typescript

你可以用一个带有注释的简单模型类将json转换为Class模型

用于工程

你可以用一个tapi.js! 这是一种轻便的自动装置,可以双向工作。

npm i -D tapi.js

然后你就可以简单地做了

let typedObject = new YourClass().fromJSON(jsonData)

或者用承诺

axios.get(...).as(YourClass).then(typedObject => { ... })

你可以在文档里读到更多。

您可以像这样将json转换为属性

class Jobs {
  constructor(JSONdata) {
    this.HEAT = JSONdata.HEAT;    
    this.HEAT_EAF = JSONdata.HEAT_EAF;    
  }
  
}

 var job = new Jobs({HEAT:'123',HEAT_EAF:'456'});