Given following example:
var test = {
"company_name": "Foobar",
"example": "HelloWorld",
"address": {
"street": "My Street 12",
"example": "BarFoo",
"details": "Berlin",
}
}
console.log(JSON.stringify(test, ['company_name','address','street','example']));
// What I actually want
// console.log(JSON.stringify(test, ['company_name','address.street','address.example']));
How can I use JSON's stringify function to deal with nested objects properly?
Since I have huge JSON objects it happens that a key of a nested object is identical to it's "parent" object. I would like to specify my whitelist more granulary.
If your deeply-nested object or array only includes certain primitive values (strings, numbers, boolean, and null), then you can use JSON. parse() & JSON. stringify() to deep copy without issues.
Attributes and event data can contain nested (JSON) values—arrays, objects, and arrays of objects.
To create a nested object, call createNestedObject() . To create a nested array, call createNestedArray() .
JSON.stringify() calls toJSON with one parameter, the key , which has the same semantic as the key parameter of the replacer function: if this object is a property value, the property name. if it is in an array, the index in the array, as a string.
If you're willing to go to the effort of whitelisting, then you can establish an array of valid keys, which can provide the ability to nest similar to how many systems do JSON nesting (a .
separator, or any separator of your choosing).
var whitelistedObj = whitelistJson(obj, ["company_name", "example", "address.street", "address.example"]);
function whitelistJson(obj, whitelist, separator) {
var object = {};
for (var i = 0, length = whitelist.length; i < length; ++i) {
var k = 0,
names = whitelist[i].split(separator || '.'),
value = obj,
name,
count = names.length - 1,
ref = object,
exists = true;
// fill in any empty objects from first name to end without
// picking up neighboring fields
while (k < count) { // walks to n - 1
name = names[k++];
value = value[name];
if (typeof value !== 'undefined') {
if (typeof object[name] === 'undefined') {
ref[name] = {};
}
ref = ref[name];
}
else {
exists = false;
break;
}
}
if (exists) {
ref[names[count]] = value[names[count]];
}
}
return object;
}
I have a JSFiddle showing its usage as well (to ensure it actually worked on my admittedly small sample set).
You can add toJSON method in your huge JSON objects:
var test = {
"company_name": "Foobar",
"example": "HelloWorld",
"address": {
"street": "My Street 12",
"example": "BarFoo",
"details": "Berlin",
},
toJSON: function () {
return {
company_name: this.company_name,
address: {
street: this.address.street,
example: this.address.example
}
}
}
}
And, you get:
console.log(JSON.stringify(test)); // "{"company_name":"Foobar","address":{"street":"My Street 12","example":"BarFoo"}}"
Or, you can use some filter function: (this function using lodash)
function filter(object, keys, sep) {
sep = sep || '.';
var result = {};
_.each(keys, function (key) {
var keyParts = key.split(sep),
res = object,
branch = {},
branchPart = branch;
for (var i = 0; i < keyParts.length; i++) {
key = keyParts[i];
if (!_.has(res, key)) {
return;
}
branchPart[key] = _.isObject(res[key]) ? {} : res[key];
branchPart = branchPart[key];
res = res[key];
}
_.merge(result, branch);
});
return result;
}
console.log(JSON.stringify(filter(test, ['company_name', 'address.street', 'address.example']))); // "{"company_name":"Foobar","address":{"street":"My Street 12","example":"BarFoo"}}"
Check out jsfiddle http://jsfiddle.net/SaKhG/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With