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

人气:773 发布:2022-10-16 标签: json angular stringify

问题描述

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

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

在本地创建对象可以很好地工作,并且可以使用stringify调用toJSON()方法.

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

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

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

它已保存并返回,但是从那时起,当我再次进行字符串化和保存时,它不会调用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();
      });
  }

为什么toJSON()仅在新对象上起作用?

Why does toJSON() only work on new objects?

推荐答案

实际上,您的问题与Angular或Typescript无关,这只是一些JavaScript以及序列化工作原理和为什么我们是否序列化对象.

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.

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

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

当您从API返回对象"时,您将返回解析为JSON序列化对象的字符串.然后,您将获得一个 plain JavaScript对象,而不是您的类的实例.

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原型没有toJSON方法,即使有,它也不是您在Template类中编写的方法,因此不会被调用.

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

您将看到obj不是Template的实例.它只是一个对象,恰好碰巧将所有字段都作为您的原始对象作为Template实例制成,但它不是该类的实例.

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.

190