sequelize: Instance#toJSON doesn't apply included models customized toJSON
Using eager loading, I have a custom toJSON
function to prevent important data from Users
to go outside backend.
toJSON: function () {
var values = this.get();
delete values.someValue;
delete values.anothervalue;
return values;
}
When doing Product.findAll({include: [User]})
that custom toJSON from User doesn’t get called.
I did a custom toJSON
into Product
to prevent included Users
to go with those values but the problem is not only Product
needs eager load with User
but also another 5 models.
Is there any way to use custom toJSON
on User
when including it on eager load?
Here is the custom Product#toJSON
function
toJSON: function () {
var values = this.get();
if (values.User) {
delete values.User.someValue;
delete values.User.anotherValue;
}
return values;
}
About this issue
- Original URL
- State: open
- Created 9 years ago
- Reactions: 3
- Comments: 16 (4 by maintainers)
I think it might be a good idea to change the current Sequelize behavior to recursively respect custom
toJSON
s that could be defined around.Sorry to bother you @mickhansen, do you remember why not to support this? Is there any downside?
In other words, why not change the current behavior, as shown by you:
To recursively call
toJSON
instead of callingget({plain: true})
?Recursively calling
toJSON
would, in turn, automatically callget({plain: true})
anyway, unless a customtoJSON
was defined there…In my use-case I don’t just want to hide fields, I just want to use a custom toJSON() function that is used for included instances as well.
On Mon, Jun 15, 2020 at 10:15:25, Johan le Roux < notifications@github.com > wrote:
@lukeberry99 I was able to solve this by adding a getter method to the field that returns undefined, like below:
See my answer on SO for more details - https://stackoverflow.com/a/59337434/1346528
Here is what i did to solve this issue:
We use a base model class. All of our models extend from this abstract class.
Inside, we override both
toJSON
andget
methods.The main idea is to check in the overriden
get
method if we are in atoJSON
serialization context.Notice the extra parameter that we add in the get
options
object.Also we must delete the unwanted fields only when the
get
method is called for retrieving all fields, and not a unique field.So we simply check the arguments, if a string property is provided, then we just return the original return value.
Otherwise, we check if we have an options objet, and if it contains our special “toJSON” option. If it is the case, then we can safely delete the
removeFromJson
fields.We need to declare our non-serializable fields in our sub classes, like this:
Now the toJSON method will delete every field included in
removeFromJson
, and recursively in nested instances of other models (for as long as they extend the BaseModel class as well of course).What do you think ?
Sure, you can still overwrite
toJSON
, but just remember it isn’t necessarily called if the child of another instance. In that case you’ll have to overwrite the parent toJSON aswell so it doesn’t callget
like Sequelize does by default.