Angular4 - why does custom toJSON() only get called on new objects?

寵の児 提交于 2019-12-13 08:44:59

问题


I have this code. Notice that the serialization is simply renaming the template_items property to 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>
}

Creating an object locally works fine and stringify calls the toJSON() method.

However, once I send that object to the 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();
      });
  }

It is saved and returned, but from that point on when I stringify and save again it does NOT call 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();
      });
  }

Why does toJSON() only work on new objects?


回答1:


In fact, your question has nothing to do with Angular or Typescript, it's just some JavaScript and the logic of how serialization work and why do we serialize objects.

I send that object to the API, save and return it

When you return an "object" from an API, you're returning a string which you parse as a JSON serialized object. Then you get a plain JavaScript object, not an instance of your class.

Object prototype in JavaScript does not have toJSON method, and even if it had, it's not the method you've written inside the Template class, so it won't be called.

You don't even need a server call to replicate this, just do

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

And you'll see that obj is not an instance of Template. It's simply an object which simply happens to have all the fields as your original object made as a Template instance, but it's not an instance of that class.



来源:https://stackoverflow.com/questions/46863066/angular4-why-does-custom-tojson-only-get-called-on-new-objects

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!