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

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

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


当前回答

对我来说,这很有效。我使用函数 对象。分配(目标,源…)。 首先,创建正确的对象,然后将数据从json对象复制到目标。例子:

let u:User = new User();
Object.assign(u , jsonUsers);

还有一个更高级的使用例子。一个使用数组的例子。

this.someService.getUsers().then((users: User[]) => {
  this.users = [];
  for (let i in users) {
    let u:User = new User();
    Object.assign(u , users[i]);
    this.users[i] = u;
    console.log("user:" + this.users[i].id);
    console.log("user id from function(test it work) :" + this.users[i].getId());
  }

});

export class User {
  id:number;
  name:string;
  fullname:string;
  email:string;

  public getId(){
    return this.id;
  }
}

其他回答

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

npm i -D tapi.js

然后你就可以简单地做了

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

或者用承诺

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

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

Java爱好者

创建POJO类

export default class TransactionDTO{
    constructor() {
    }
}

按类创建空对象

let dto = new TransactionDto()   // ts object
let json = {name:"Kamal",age:40} // js object

let transaction: TransactionDto = Object.assign(dto,JSON.parse(JSON.stringify(json)));//conversion

对我来说,这很有效。我使用函数 对象。分配(目标,源…)。 首先,创建正确的对象,然后将数据从json对象复制到目标。例子:

let u:User = new User();
Object.assign(u , jsonUsers);

还有一个更高级的使用例子。一个使用数组的例子。

this.someService.getUsers().then((users: User[]) => {
  this.users = [];
  for (let i in users) {
    let u:User = new User();
    Object.assign(u , users[i]);
    this.users[i] = u;
    console.log("user:" + this.users[i].id);
    console.log("user id from function(test it work) :" + this.users[i].getId());
  }

});

export class User {
  id:number;
  name:string;
  fullname:string;
  email:string;

  public getId(){
    return this.id;
  }
}

假设json具有与typescript类相同的属性,你不需要将json属性复制到typescript对象中。你只需要在构造函数中传递json数据来构造Typescript对象。

在你的ajax回调中,你会收到一个company:

onReceiveCompany( jsonCompany : any ) 
{
   let newCompany = new Company( jsonCompany );

   // call the methods on your newCompany object ...
}

为了使它起作用:

1)在Typescript类中添加一个构造函数,将json数据作为参数。在该构造函数中,使用jQuery扩展json对象,如下所示:extend(this, jsonData)。美元。扩展允许保留javascript原型,同时添加json对象的属性。

2)注意你必须对链接对象做同样的事情。在本例中的Employees中,还创建了一个构造函数,用于接收Employees的json数据部分。你调用$。将json雇员转换为typescript雇员对象。

export class Company
{
    Employees : Employee[];

    constructor( jsonData: any )
    {
        $.extend( this, jsonData);

        if ( jsonData.Employees )
            this.Employees = $.map( jsonData.Employees , (emp) => {
                return new Employee ( emp );  });
    }
}

export class Employee
{
    name: string;
    salary: number;

    constructor( jsonData: any )
    {
        $.extend( this, jsonData);
    }
}

这是我在处理Typescript类和json对象时发现的最佳解决方案。

这是一个老问题,答案基本正确,但不是很有效。我的建议是:

创建一个基类,其中包含init()方法和静态强制转换方法(用于单个对象和数组)。静态方法可以在任何地方;带有基类和init()的版本允许随后进行简单的扩展。

export class ContentItem {
    // parameters: doc - plain JS object, proto - class we want to cast to (subclass of ContentItem)
    static castAs<T extends ContentItem>(doc: T, proto: typeof ContentItem): T {
        // if we already have the correct class skip the cast
        if (doc instanceof proto) { return doc; }
        // create a new object (create), and copy over all properties (assign)
        const d: T = Object.create(proto.prototype);
        Object.assign(d, doc);
        // reason to extend the base class - we want to be able to call init() after cast
        d.init(); 
        return d;
    }
    // another method casts an array
    static castAllAs<T extends ContentItem>(docs: T[], proto: typeof ContentItem): T[] {
        return docs.map(d => ContentItem.castAs(d, proto));
    }
    init() { }
}

类似的机制(使用assign())已经在@Adam111p的帖子中提到过。只是另一种(更完整的)方法。@Timothy Perez批评assign(),但恕我直言,它在这里是完全合适的。

实现一个派生类(实类):

import { ContentItem } from './content-item';

export class SubjectArea extends ContentItem {
    id: number;
    title: string;
    areas: SubjectArea[]; // contains embedded objects
    depth: number;

    // method will be unavailable unless we use cast
    lead(): string {
        return '. '.repeat(this.depth);
    }

    // in case we have embedded objects, call cast on them here
    init() {
        if (this.areas) {
            this.areas = ContentItem.castAllAs(this.areas, SubjectArea);
        }
    }
}

现在我们可以强制转换从service检索到的对象:

const area = ContentItem.castAs<SubjectArea>(docFromREST, SubjectArea);

SubjectArea对象的所有层次结构都将具有正确的类。

用例/例子;创建一个Angular服务(还是抽象基类):

export abstract class BaseService<T extends ContentItem> {
  BASE_URL = 'http://host:port/';
  protected abstract http: Http;
  abstract path: string;
  abstract subClass: typeof ContentItem;

  cast(source: T): T {
    return ContentItem.castAs(source, this.subClass);
  }
  castAll(source: T[]): T[] {
    return ContentItem.castAllAs(source, this.subClass);
  }

  constructor() { }

  get(): Promise<T[]> {
    const value = this.http.get(`${this.BASE_URL}${this.path}`)
      .toPromise()
      .then(response => {
        const items: T[] = this.castAll(response.json());
        return items;
      });
    return value;
  }
}

用法变得非常简单;创建Area服务:

@Injectable()
export class SubjectAreaService extends BaseService<SubjectArea> {
  path = 'area';
  subClass = SubjectArea;

  constructor(protected http: Http) { super(); }
}

服务的get()方法将返回一个已转换为SubjectArea对象的数组的Promise(整个层次结构)

现在,我们有另一个类:

export class OtherItem extends ContentItem {...}

创建一个检索数据并转换为正确类的服务非常简单:

@Injectable()
export class OtherItemService extends BaseService<OtherItem> {
  path = 'other';
  subClass = OtherItem;

  constructor(protected http: Http) { super(); }
}