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

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

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


当前回答

虽然它本身不是铸造;我发现https://github.com/JohnWhiteTB/TypedJSON是一个有用的替代方案。

@JsonObject
class Person {
    @JsonMember
    firstName: string;

    @JsonMember
    lastName: string;

    public getFullname() {
        return this.firstName + " " + this.lastName;
    }
}
var person = TypedJSON.parse('{ "firstName": "John", "lastName": "Doe" }', Person);

person instanceof Person; // true
person.getFullname(); // "John Doe"

其他回答

如果你需要将json对象转换为typescript类,并在结果对象中使用它的实例方法,你需要使用object。setPrototypeOf,就像我在下面的代码片段中所做的那样:

Object.setPrototypeOf(jsonObject, YourTypescriptClass.prototype)

使用“as”声明:

const data = JSON.parse(response.data) as MyClass;

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

创建一个基类,其中包含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(); }
}

使用从接口扩展的类。

然后:

    Object.assign(
        new ToWhat(),
        what
    )

和最好的:

    Object.assign(
        new ToWhat(),
        <IDataInterface>what
    )

ToWhat成为DataInterface的控制器

https://jvilk.com/MakeTypes/

您可以使用该网站为您生成代理。它生成一个类,可以解析和验证输入的JSON对象。