How do I initialize a TypeScript object with a JSON object

前端 未结 16 861
被撕碎了的回忆
被撕碎了的回忆 2020-11-22 08:30

I receive a JSON object from an AJAX call to a REST server. This object has property names that match my TypeScript class (this is a follow-on to this question).

Wha

16条回答
  •  执笔经年
    2020-11-22 08:52

    I personally prefer option #3 of @Ingo Bürk. And I improved his codes to support an array of complex data and Array of primitive data.

    interface IDeserializable {
      getTypes(): Object;
    }
    
    class Utility {
      static deserializeJson(jsonObj: object, classType: any): T {
        let instanceObj = new classType();
        let types: IDeserializable;
        if (instanceObj && instanceObj.getTypes) {
          types = instanceObj.getTypes();
        }
    
        for (var prop in jsonObj) {
          if (!(prop in instanceObj)) {
            continue;
          }
    
          let jsonProp = jsonObj[prop];
          if (this.isObject(jsonProp)) {
            instanceObj[prop] =
              types && types[prop]
                ? this.deserializeJson(jsonProp, types[prop])
                : jsonProp;
          } else if (this.isArray(jsonProp)) {
            instanceObj[prop] = [];
            for (let index = 0; index < jsonProp.length; index++) {
              const elem = jsonProp[index];
              if (this.isObject(elem) && types && types[prop]) {
                instanceObj[prop].push(this.deserializeJson(elem, types[prop]));
              } else {
                instanceObj[prop].push(elem);
              }
            }
          } else {
            instanceObj[prop] = jsonProp;
          }
        }
    
        return instanceObj;
      }
    
      //#region ### get types ###
      /**
       * check type of value be string
       * @param {*} value
       */
      static isString(value: any) {
        return typeof value === "string" || value instanceof String;
      }
    
      /**
       * check type of value be array
       * @param {*} value
       */
      static isNumber(value: any) {
        return typeof value === "number" && isFinite(value);
      }
    
      /**
       * check type of value be array
       * @param {*} value
       */
      static isArray(value: any) {
        return value && typeof value === "object" && value.constructor === Array;
      }
    
      /**
       * check type of value be object
       * @param {*} value
       */
      static isObject(value: any) {
        return value && typeof value === "object" && value.constructor === Object;
      }
    
      /**
       * check type of value be boolean
       * @param {*} value
       */
      static isBoolean(value: any) {
        return typeof value === "boolean";
      }
      //#endregion
    }
    
    // #region ### Models ###
    class Hotel implements IDeserializable {
      id: number = 0;
      name: string = "";
      address: string = "";
      city: City = new City(); // complex data
      roomTypes: Array = []; // array of complex data
      facilities: Array = []; // array of primitive data
    
      // getter example
      get nameAndAddress() {
        return `${this.name} ${this.address}`;
      }
    
      // function example
      checkRoom() {
        return true;
      }
    
      // this function will be use for getting run-time type information
      getTypes() {
        return {
          city: City,
          roomTypes: RoomType
        };
      }
    }
    
    class RoomType implements IDeserializable {
      id: number = 0;
      name: string = "";
      roomPrices: Array = [];
    
      // getter example
      get totalPrice() {
        return this.roomPrices.map(x => x.price).reduce((a, b) => a + b, 0);
      }
    
      getTypes() {
        return {
          roomPrices: RoomPrice
        };
      }
    }
    
    class RoomPrice {
      price: number = 0;
      date: string = "";
    }
    
    class City {
      id: number = 0;
      name: string = "";
    }
    // #endregion
    
    // #region ### test code ###
    var jsonObj = {
      id: 1,
      name: "hotel1",
      address: "address1",
      city: {
        id: 1,
        name: "city1"
      },
      roomTypes: [
        {
          id: 1,
          name: "single",
          roomPrices: [
            {
              price: 1000,
              date: "2020-02-20"
            },
            {
              price: 1500,
              date: "2020-02-21"
            }
          ]
        },
        {
          id: 2,
          name: "double",
          roomPrices: [
            {
              price: 2000,
              date: "2020-02-20"
            },
            {
              price: 2500,
              date: "2020-02-21"
            }
          ]
        }
      ],
      facilities: ["facility1", "facility2"]
    };
    
    var hotelInstance = Utility.deserializeJson(jsonObj, Hotel);
    
    console.log(hotelInstance.city.name);
    console.log(hotelInstance.nameAndAddress); // getter
    console.log(hotelInstance.checkRoom()); // function
    console.log(hotelInstance.roomTypes[0].totalPrice); // getter
    // #endregion
    
    

提交回复
热议问题