To simplify understanding, I will create an example closer to reality:
const obj = {
"name": "John Doe",
"age": 34,
"parents": [
{
"name": "Derp",
"age": 63,
"gender": "male"
}, {
"name": "Derpina",
"age": 62,
"gender": "female"
}
]
};
Assuming the intention is to serialize the object obj
ignoring the attribute age
. One detail is that not only the object itself has the attribute age
, as also children objects possess (in this case, the two objects in parents
). If the intention in this case is to remove all attributes age
, no matter where you are, there are two solutions (others have been addressed in the other answers):
First solution: pass as the second parameter of JSON.stringify
a list of attributes you want to keep when serializing the object. However, this list of attributes should not only address the attributes of the original object, but all attributes of all related objects that it is desired to maintain. For example, the internal objects a parents
have the attribute gender
that the main object does not possess and yet such an attribute must be listed:
const obj = {
"name": "John Doe",
"age": 34,
"parents": [
{
"name": "Derp",
"age": 63,
"gender": "male"
}, {
"name": "Derpina",
"age": 62,
"gender": "female"
}
]
};
console.log(JSON.stringify(obj, ["name", "parents", "gender"]));
If gender
is not listed, the attribute will be removed from the internal objects when serializing.
Second solution: also using the second parameter of JSON.stringify
, but now defining a function that will execute the logic of whether or not to keep a value in the object. The function takes two parameters: the key, attribute name, and its value. The logic here would be very simple: if the key matches the attribute we want to remove, we return the value undefined
, otherwise returns the value itself.
const obj = {
"name": "John Doe",
"age": 34,
"parents": [
{
"name": "Derp",
"age": 63,
"gender": "male"
}, {
"name": "Derpina",
"age": 62,
"gender": "female"
}
]
};
console.log(JSON.stringify(obj, function (key, value) {
if (key == "age") {
return undefined;
}
return value;
}));
This form is relatively more versatile than the first, because instead of specifying which attributes you want to keep, you specify which attributes you want to remove, regardless of the structure of the rest of the object.
Not modifying internal objects
Both solutions remove the attribute from the innermost objects, so if the intention is to keep them, by removing the attribute from the main object, other solutions are needed.
Function toJSON: as presented in response from L.Albano, it is possible to define a function toJSON
in the object that will be called to serialize it. The result of serialization will actually be the serialization of the return of this function. L. Albano showed how to clone the object manually, but it is possible to do it dynamically and then remove the desired attribute.
const obj = {
"name": "John Doe",
"age": 34,
"parents": [
{
"name": "Derp",
"age": 63,
"gender": "male"
}, {
"name": "Derpina",
"age": 62,
"gender": "female"
}
],
toJSON: function () {
// Clona o objeto:
const clone = Object.assign({}, this);
// Remove o atributo desejado:
delete clone["age"];
// Retorna o clone modificado:
return clone;
}
};
console.log(JSON.stringify(obj));
Thus, only the attribute age
of the main object is removed, while the internal objects are maintained.
Clone the object using Object.assign
only possible from Ecmascript 5 (ES6), but if desired, there are polyfills. Another technique of cloning objects is matching JSON.parse
with JSON.stringify
, but this technique is not applicable in this example because it would generate an infinite recursion.
Do you want to prevent some properties from being passed to JSON? and you know beforehand what they are?
– Sergio
@Sergio, in this case, I know which ones I don’t want, therefore, except those I don’t want, all should be serialized
– Artur Trapp
Interesting question and 3 interesting answers! Everyone wins :)
– Sergio