问题
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