Angular4 - 为什么自定义toJSON()只在新对象上调用?

时间:2017-10-21 12:08:10

标签: json angular stringify

我有这个代码。请注意,序列化只是将template_items属性重命名为template_items_attributes:

export class Template {
  constructor(
  ) {}

  public id: string
  public account_id: string
  public name: string
  public title: string
  public info: string
  public template_items: Array<TemplateItem>

  toJSON(): ITemplateSerialized {
    return {
      id: this.id,
      account_id: this.account_id,
      name: this.name,
      title: this.title,
      info: this.info,
      template_items_attributes: this.template_items
    }
  }
}


export interface ITemplateSerialized {
  id: string,
  account_id: string,
  name: string,
  title: string,
  info: string,
  template_items_attributes: Array<TemplateItem>
}

在本地创建对象工作正常,stringify调用toJSON()方法。

但是,一旦我将该对象发送到API:

  private newTemplate(name: string): Template {
    let template = new Template();
    template.name = name;
    template.account_id = this._userService.user.account_id;
    // next 5 lines are for testing that toJSON() is called on new obj
    let item = new TemplateItem();
    item.content = "Test"
    template.template_items.push(item);
    let result = JSON.stringify(template);
    console.log('ready', result); // SHOWS the property changes
    return template;
  }

  postTemplate(name: string): Observable<any> {
    return this._authService.post('templates', JSON.stringify(this.newTemplate(name)))
      .map((response) => {
        return response.json();
      });
  }

它被保存并返回,但从那时起我进行字符串化并再次保存时,它不会调用toJSON()。

  patchTemplate(template: Template): Observable<any> {
    console.log('patching', JSON.stringify(template)); // DOES NOT CHANGE!
    return this._authService.patch('templates' + `/${template.id}`, JSON.stringify(template))
      .map((response) => {
        return response.json();
      });
  }

为什么toJSON()只适用于新对象?

1 个答案:

答案 0 :(得分:1)

事实上,你的问题与Angular或Typescript无关,它只是一些JavaScript和序列化工作的逻辑以及为什么我们序列化对象。

  

我将该对象发送给API,保存并返回

当您从API返回“对象”时,您将返回一个字符串,您将其解析为JSON序列化对象。然后你得到一个普通的 JavaScript对象,不是你的类的一个实例。

JavaScript中的

Object原型没有toJSON方法,即使它有,也不是你在Template类中编写的方法,所以它不会调用。

您甚至不需要服务器调用来复制它,只需执行

const obj = JSON.parse(JSON.stringify(new Template()))
obj.toJSON // undefined

您会发现obj不是Template的实例。它只是一个对象,它恰好将所有字段作为原始对象制作为Template实例,但它不是该类的实例。