【问题标题】:How do I cast a JSON Object to a TypeScript class?如何将 JSON 对象转换为 TypeScript 类?
【发布时间】:2014-05-17 12:35:51
【问题描述】:

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

我不想填充 typescript var(即有一个构造函数接受这个 JSON 对象)。它很大,并且逐个子对象和逐个属性地跨子对象复制所有内容将花费大量时间。

更新:不过你可以cast it to a typescript interface!

【问题讨论】:

标签: json typescript


【解决方案1】:

您不能简单地将来自 Ajax 请求的普通 JavaScript 结果转换为原型 JavaScript/TypeScript 类实例。有许多技术可以做到这一点,通常涉及复制数据。除非您创建该类的实例,否则它不会有任何方法或属性。它将仍然是一个简单的 JavaScript 对象。

如果您只处理数据,您可以只对接口进行强制转换(因为它纯粹是一个编译时结构),这需要您使用一个使用数据实例并执行操作的 TypeScript 类数据。

复制数据的一些例子:

  1. Copying AJAX JSON object into existing Object
  2. Parse JSON String into a Particular Object Prototype in JavaScript

本质上,您只需:

var d = new MyRichObject();
d.copyInto(jsonResult);

【讨论】:

  • 我同意你的回答。另外,虽然我现在无法查找和测试它,但我认为这两个步骤可以通过将唤醒函数作为参数提供给JSON.parse() 来组合。两者仍然需要完成,但在语法上它们可以结合起来。
  • 当然,这也可能有效——我不知道它是否会更有效,因为它需要为每个属性调用额外的函数调用。
  • 绝对不是我要找的答案 :( 出于好奇,为什么会这样?在我看来,javascript 的工作方式应该是可行的。
  • Object.setPrototypeOf怎么样
  • 我一直在做Object.assign(new ApiAuthData(), JSON.parse(rawData))
【解决方案2】:

我遇到了同样的问题,我找到了一个可以完成这项工作的库:https://github.com/pleerock/class-transformer。

它是这样工作的:

let jsonObject = response.json() as Object;
let fooInstance = plainToClass(Models.Foo, jsonObject);
return fooInstance;

它支持嵌套子级,但你必须装饰你的班级成员。

【讨论】:

  • 这个出色的小库以最少的努力完美地解决了它(不过不要忘记您的 @Type 注释)。这个答案值得更多的信任。
  • 哇哦!这个库不是那么小,它可能有你需要的一切,甚至可以让你用@transform装饰器控制转换:D
  • 请注意,这个库几乎不再维护。它不再适用于 Angular5+,而且他们甚至不再合并拉取请求,我认为他们不会很快解决这个问题。不过,这是一个很棒的图书馆。
  • 这在 Angular 6 中工作得很好(至少对于我的用例来说,它只是从字面上映射 JSON 类)
  • 使用 angular8+ 并且正在积极开发中。对我来说,这是最重要的实用程序库之一
【解决方案3】:

在 TypeScript 中,您可以使用如下接口和泛型来执行 type assertion:

var json = Utilities.JSONLoader.loadFromFile("../docs/location_map.json");
var locations: Array<ILocationMap> = JSON.parse(json).location;

其中 ILocationMap 描述了数据的形状。这种方法的优点是你的 JSON 可以包含更多的属性,但形状满足接口的条件。

但是,这不会添加类实例方法。

【讨论】:

  • 仅供参考:这是一个类型断言,而不是强制转换。
  • 请参阅 here 了解 type assertion 和 cast 之间的区别。
  • 在哪里可以找到 Utilities.JSONLoader?
  • 但它不会有任何方法,如答案中所述。
  • 重点是能够使用在类型中实现的方法。
【解决方案4】:

如果你使用的是 ES6,试试这个:

class Client{
  name: string

  displayName(){
    console.log(this.name)
  }
}

service.getClientFromAPI().then(clientData => {
  
  // Here the client data from API only have the "name" field
  // If we want to use the Client class methods on this data object we need to:
  let clientWithType = Object.assign(new Client(), clientData)

  clientWithType.displayName()
})

但遗憾的是,此方法不适用于嵌套对象。

【讨论】:

  • 他们在 Typescript 中要求它。
  • 嗨@joe.feser,我提到ES6是因为这种方式需要'Object.assign'方法。
  • 如果没有默认构造函数,可以通过Object.create(MyClass.prototype)创建目标实例,完全绕过构造函数。
  • 更多关于嵌套对象限制的解释见stackoverflow.com/questions/22885995/…
【解决方案5】:

我发现了一篇关于将 JSON 泛型转换为 Typescript 类的非常有趣的文章:

http://cloudmark.github.io/Json-Mapping/

你最终得到以下代码:

let example = {
                "name": "Mark", 
                "surname": "Galea", 
                "age": 30, 
                "address": {
                  "first-line": "Some where", 
                  "second-line": "Over Here",
                  "city": "In This City"
                }
              };

MapUtils.deserialize(Person, example);  // custom class

【讨论】:

  • 的 JSON 映射器文章链接很好阅读。
【解决方案6】:

目前还没有任何东西可以自动检查您从服务器收到的 JSON 对象是否具有预期的(读取符合)typescript 的接口属性。但是你可以使用User-Defined Type Guards

考虑以下接口和一个愚蠢的 json 对象(它可以是任何类型):

interface MyInterface {
    key: string;
 }

const json: object = { "key": "value" }

三种可能的方式:

A.类型断言或简单的静态转换放在变量之后

const myObject: MyInterface = json as MyInterface;

B.简单的静态转换,在变量之前和菱形之间

const myObject: MyInterface = <MyInterface>json;

C.高级动态转换,你自己检查对象的结构

function isMyInterface(json: any): json is MyInterface {
    // silly condition to consider json as conform for MyInterface
    return typeof json.key === "string";
}

if (isMyInterface(json)) {
    console.log(json.key)
}
else {
        throw new Error(`Expected MyInterface, got '${json}'.`);
}

你可以play with this example here

注意这里的难点是写isMyInterface函数。我希望 TS 迟早会在 export complex typing 到运行时添加一个装饰器,并让运行时在需要时检查对象的结构。现在,您可以使用目的大致相同的 json 模式验证器或 runtime type check function generator

【讨论】:

    【解决方案7】:

    TLDR:一个班轮

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

    详细答案

    我会不推荐 Object.assign 方法,因为它可能不恰当地用未在其中声明的不相关属性(以及定义的闭包)乱扔您的类实例类本身。

    在您尝试反序列化的类中,我会确保定义了您想要反序列化的任何属性(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 抱怨参数类型不兼容,只需使用尖括号 &lt;YourClassName&gt; 将参数转换为相同类型,例如:

    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 和任务列表反序列化到它们各自的类实例中。

    【讨论】:

    • 我收到此错误消息:类型“{ name: string, age: number, id: number }”无法转换为类型“Person”。属性“id”在“Person”类型中是私有的,但在“{ name: string, age: number, id: number }”类型中不是私有的
    • 我应该如何将它与枚举一起使用?我是否必须使用特定类型的方法并为其添加 getter 和 setter?
    • @TimothyParez 你什么时候设置任务?
    • 我尝试做类似的事情,但是当我 console.log 人时我的任务数组是空的。
    • 为了编译,我必须在类中添加一个索引签名:export class Person { [key: string]: any (...) }
    【解决方案8】:

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

    在您的 ajax 回调中,您收到一个公司:

    onReceiveCompany( jsonCompany : any ) 
    {
       let newCompany = new Company( jsonCompany );
    
       // call the methods on your newCompany object ...
    }
    

    为了完成这项工作:

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

    2) 请注意,您必须对链接对象执行相同操作。对于示例中的员工,您还创建了一个构造函数,获取员工的部分 json 数据。您调用 $.map 将 json 员工转换为打字稿 Employee 对象。

    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 对象时发现的最佳解决方案。

    【讨论】:

    • 我更喜欢这个解决方案而不是实现和维护接口,因为我的 Angular2 应用程序有一个真实的应用程序模型,它可能与我的应用程序使用的 web 服务的模型不同。它可以有私有数据和计算属性。
    • 在 Angular 项目中使用 JQuery 是一个糟糕的主意。如果你的模型包含一堆函数,它们就不再是模型了。
    • @Davor 你是说 POJO,还是模特? POJO(基本上是普通对象)没有任何功能,而模型是一个更广泛的术语,它包括存储库。与 POJO 相比,存储库模式是关于函数的,但它仍然是模型。
    • @Davor:在 Angular 项目中使用 JQuery 并不是一个坏主意,只要你不使用它来操作 DOM,这确实是一个糟糕的主意。我确实使用了我的 Angular 项目所需的任何库,而对于 jQuery,这不是一个选项,因为我的项目使用依赖于它的 SignalR。对于现在由 javascript ES6 使用的类,使用属性访问数据,这些属性是封装数据在内存中存储方式的函数。对于构造函数,有一种使用工厂的正确方法。
    • OP 显然是关于 REST 的纯数据模型。伙计们,你让事情变得不必要地复杂了。是的,您可以将 Jquery 用于其他内容,但您要导入一个庞大的库来使用其中的 1%。如果我见过的话,那是一种代码味道。
    【解决方案9】:

    就我而言,它有效。我使用了函数 Object.assign(目标、来源...)。 首先,创建正确的对象,然后将数据从 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;
      }
    }
    

    【讨论】:

    • 拥有私有财产会怎样?
    • 因为 jsonUser 对象不是 User 类。无操作 Object.assign(u, jsonUsers);您不能使用 getId() 函数。只有在分配后,您才能获得一个有效的用户对象,您可以在其中使用 getId() 函数。 getId() 函数仅用于操作成功的示例。
    • 您可以跳过临时变量 - 只需执行 this.users[i] = new User(); Object.assign(this.users[i], users[i])
    • 或者更好地利用返回值:this.users[i] = Object.assign(new User(), users[i]);
    • 本长版仅作说明之用。您可以随意缩短代码 :)
    【解决方案10】:

    虽然它本身不是投射;我发现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"
    

    【讨论】:

    • 它不投射,它到底是做什么的?
    • 此解决方案需要大量注释。真的没有更简单的方法吗?
    【解决方案11】:

    使用“as”声明:

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

    【讨论】:

    • 该技术在this answer from two years prior 中被提及,并且正如在其他地方所讨论的,不添加任何可能在MyClass 上声明的函数。
    • 我认为这对于通常没有功能的模型对象使用它非常有效。
    • 您这样做的唯一原因是准备对结果对象执行处理 - 表明需要一种也提供功能的转换方法。请参阅我上面的答案,它提供了上述和功能的等价物。
    • 这不适用于空对象。这样的解析将返回普通的Object
    【解决方案12】:

    我个人觉得打字稿不允许指定端点定义令人震惊 接收对象的类型。看来确实如此, 我会做我对其他语言所做的事情,那就是我会将 JSON 对象与类定义分开, 并让类定义使用 JSON 对象作为其唯一的数据成员。

    我鄙视样板代码,所以对我来说,通常是在保留类型的同时用最少的代码达到预期的结果。

    考虑以下 JSON 对象结构定义 - 这些将是您在端点收到的内容,它们只是结构定义,没有方法。

    interface IAddress {
        street: string;
        city: string;
        state: string;
        zip: string;
    }
    
    interface IPerson {
        name: string;
        address: IAddress;
    }
    

    如果我们用面向对象的术语来考虑上面的内容,上面的接口不是类,因为它们只定义了一个数据结构。 OO 术语中的类定义了数据和对其进行操作的代码。

    所以我们现在定义一个类来指定数据和对其进行操作的代码...

    class Person {
        person: IPerson;
    
        constructor(person: IPerson) {
            this.person = person;
        }
    
        // accessors
        getName(): string {
            return person.name;
        }
    
        getAddress(): IAddress {
            return person.address;
        }
    
        // You could write a generic getter for any value in person, 
        // no matter how deep, by accepting a variable number of string params
    
        // methods
        distanceFrom(address: IAddress): float {
            // Calculate distance from the passed address to this persons IAddress
            return 0.0;
        }
    }
    

    现在我们可以简单地传入任何符合 IPerson 结构的对象并继续前进……

       Person person = new Person({
                name: "persons name",
                address: {
                    street: "A street address",
                    city: "a city",
                    state: "a state",
                    zip: "A zipcode"
                }
            });
    

    以同样的方式,我们现在可以处理在您的端点收到的对象,其内容类似于...

    Person person = new Person(req.body);    // As in an object received via a POST call
    
    person.distanceFrom({ street: "Some street address", etc.});
    

    这样的性能要高得多,并且在复制数据时使用了一半的内存,同时显着减少了您必须为每种实体类型编写的样板代码量。 它只是依赖于 TypeScript 提供的类型安全。

    【讨论】:

    • 这种方法的唯一缺点是当你 JSON.strigify(person) 时,结果将与普通 JSON 不同。换句话说,序列化产生与反序列化不同的输出。
    • @TiagoStapenhorstMartins 但是您不需要对类的实例进行字符串化。你可以只是 JSON.stringify(person.person) - 即。对象的 person 属性。 (我想,对吧?)
    • @rmcshry 是的,正确的!好吧,如果您不介意将 person 对象嵌套在另一个对象中,那么这个解决方案就可以了。
    • 在实际使用中,如果您需要将Person类中的IPerson导出为JSON-执行导出的代码很可能在Person类中找到,可能是getPersonJSON()方法。
    • 更进一步,如果您了解封装及其带来的价值,理想情况下,没有其他代码会访问 Person 内部的 IPerson - 只有 Person 中的代码应该访问 IPerson。您可能想要对 IPerson 执行的所有操作都应在 Person 类中完成 - 例如 save()、delete() 等。
    【解决方案13】:

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

    创建一个包含 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() { }
    }
    

    @Adam111p 帖子中提到了类似的机制(使用 assign())。只是另一种(更完整)的方法。 @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);
            }
        }
    }
    

    现在我们可以转换从服务中检索到的对象:

    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;
      }
    }
    

    用法变得非常简单;创建一个区域服务:

    @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(); }
    }
    

    【讨论】:

      【解决方案14】:

      您可以创建您类型的interface (SomeType) 并将对象投射到其中。

      const typedObject: SomeType = <SomeType> responseObject;
      

      【讨论】:

        【解决方案15】:

        如果您需要将 json 对象转换为 typescript 类并在生成的对象中提供其实例方法,您需要使用 Object.setPrototypeOf,就像我在下面的代码 sn-p 中所做的那样:

        Object.setPrototypeOf(jsonObject, YourTypescriptClass.prototype)
        

        【讨论】:

          【解决方案16】:

          使用从接口扩展的类。

          然后:

              Object.assign(
                  new ToWhat(),
                  what
              )
          

          最好的:

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

          ToWhat 成为DataInterface 的控制器

          【讨论】:

            【解决方案17】:

            https://jvilk.com/MakeTypes/

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

            【讨论】:

              【解决方案18】:

              我在这里使用了这个库:https://github.com/pleerock/class-transformer

              <script lang="ts">
                  import { plainToClass } from 'class-transformer';
              </script>
              

              实施:

              private async getClassTypeValue() {
                const value = await plainToClass(ProductNewsItem, JSON.parse(response.data));
              }
              

              有时您必须解析 plainToClass 的 JSON 值才能了解它是 JSON 格式的数据

              【讨论】:

              【解决方案19】:

              在最新的 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
              }
              

              【讨论】:

                【解决方案20】:

                我遇到了类似的需求。 我想要一些能让我轻松地从/到 JSON 转换的东西 来自特定类定义的 REST api 调用。 我发现的解决方案不足或打算重写我的 类的代码并添加注释或类似内容。

                我希望在 Java 中使用 GSON 之类的东西来序列化/反序列化与 JSON 对象之间的类。

                结合后面的需求,转换器也可以在JS中运行,我写完了自己的包。

                虽然有一点开销。但是启动时添加和编辑非常方便。

                你初始化模块:

                1. 转换模式 - 允许在字段之间进行映射并确定 如何进行转换
                2. 类映射数组
                3. 转换函数映射 - 用于特殊转换。

                然后在您的代码中,您使用初始化模块,如:

                const convertedNewClassesArray : MyClass[] = this.converter.convert<MyClass>(jsonObjArray, 'MyClass');
                
                const convertedNewClass : MyClass = this.converter.convertOneObject<MyClass>(jsonObj, 'MyClass');
                

                或者,转为 JSON:

                const jsonObject = this.converter.convertToJson(myClassInstance);
                
                

                使用这个 npm 包的链接以及如何使用该模块的详细说明:json-class-converter

                还包了
                角度使用: angular-json-class-converter

                【讨论】:

                  【解决方案21】:

                  将对象按原样传递给类构造函数;没有约定或检查

                  interface iPerson {
                     name: string;
                     age: number;
                  }
                  
                  class Person {
                     constructor(private person: iPerson) { }
                  
                     toString(): string {
                        return this.person.name + ' is ' + this.person.age;
                     }  
                  }
                  
                  
                  // runs this as // 
                  const object1 = { name: 'Watson1', age: 64 };
                  const object2 = { name: 'Watson2' };            // age is missing
                  
                  const person1 = new Person(object1);
                  const person2 = new Person(object2 as iPerson); // now matches constructor
                  
                  console.log(person1.toString())  // Watson1 is 64
                  console.log(person2.toString())  // Watson2 is undefined
                  

                  【讨论】:

                    【解决方案22】:

                    你可以使用这个 npm 包。 https://www.npmjs.com/package/class-converter

                    使用方便,例如:

                    class UserModel {
                      @property('i')
                      id: number;
                    
                      @property('n')
                      name: string;
                    }
                    
                    const userRaw = {
                      i: 1234,
                      n: 'name',
                    };
                    
                    // use toClass to convert plain object to class
                    const userModel = toClass(userRaw, UserModel);
                    // you will get a class, just like below one
                    // const userModel = {
                    //   id: 1234,
                    //   name: 'name',
                    // }
                    

                    【讨论】:

                      【解决方案23】:

                      你可以用一个tapi.js! 这是一个轻量级的自动映射器,可以双向工作。

                      npm i -D tapi.js
                      

                      那么你可以简单地做

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

                      或承诺

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

                      您可以在the docs 上阅读更多相关信息。

                      【讨论】:

                        【解决方案24】:

                        您可以使用 TypeScript 接口来代替类。

                        假设我们正在使用返回代表用户的 JSON 字符串的 REST API。 JSON API 同意返回字符串 firstName、字符串 lastName 和数字 id 的合同。我们将用户建模为 TypeScript 中的接口,如下所示:

                        interface User {
                           id: number;
                           firstName: string;
                           lastName: string;
                        }
                        

                        当您拥有正确的属性映射时,以下代码会很好:

                        const json = '{"id": 1, "firstName": "Bob", "lastName": "Dylan"}'; //this will come from the REST API
                        try {
                          const user: User = JSON.parse(json);
                          console.log(user);
                        } catch (e) {
                          console.log("An error on casting object has occurred", e);
                        }
                        

                        结果:

                        [LOG]: {
                          "id": 1,
                          "firstName": "Bob",
                          "lastName": "Dylan"
                        } 
                        

                        Play this code here

                        【讨论】:

                          【解决方案25】:

                          这是一个简单且非常好的选择

                          let person = "{"name":"Sam","Age":"30"}";
                          
                          const jsonParse: ((key: string, value: any) => any) | undefined = undefined;
                          let objectConverted = JSON.parse(textValue, jsonParse);
                          

                          然后你就会有

                          objectConverted.name
                          

                          【讨论】:

                            【解决方案26】:

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

                            class Jobs {
                              constructor(JSONdata) {
                                this.HEAT = JSONdata.HEAT;    
                                this.HEAT_EAF = JSONdata.HEAT_EAF;    
                              }
                              
                            }
                            
                             var job = new Jobs({HEAT:'123',HEAT_EAF:'456'});
                            

                            【讨论】:

                              猜你喜欢
                              • 1970-01-01
                              • 2018-03-26
                              • 2022-01-03
                              • 2019-11-07
                              • 2018-05-17
                              相关资源
                              最近更新 更多