I am pulling some data from a server (names of databases and specific data from each database). I then present the data to the user which chooses which entries he likes and then sends them to the server for analysis. To contain the user selections (database names and entries) I dynamically create an object which looks like this:
Because I don't know which databases I'll get and which entries, I dynamically create the object's databses names properties with Object.defineProperty like so:
Object.defineProperty(dbs_list, db_name, {
value: {},
writable: true,
configurable: true
});
After building the object I want to send it to the server as a JSON object. There I encountered my first issue. JSON.stringify didn't work on the object because (as far as I understand) the object properties weren't 'own' properties.
As I understand possible solutions are to:
- make the properties become 'own' properties - which, after some searching, I haven't figured out how to.
- make the object have a
toJSONproperty function - which is the option I chose.
Here is the gist of it:
var selected_entries = {
toJSON() {
for (db in this) {
for (entry in this[db]) {
//do something
}
}
return json_string;
}
};
But here I encounter the same issue - the properties are not 'own' properties so all I get from the first loop is the toJson property.
Is there a way to get the entries without saving them in an array and looping over it? Or, is there a way to define them as an 'own' properties?
1 Answer 1
The properties on your object are own properties. The problem is they're not enumerable. JSON.stringify only includes enumerable properties. That's also why you're not seeing them in your for-in loop. (Note: for-in doesn't only enumerate own properties, it includes inherited ones too. But only enumerable ones.)
To make your properties enumerable, add enumerable: true to your call to defineProperty; like all the flags, it defaults to false.
Object.defineProperty(dbs_list, db_name, {
value: {},
writable: true,
configurable: true
});
But, at that point, you're just defining a data property anyway, so it would be simpler to simply do:
dbs_list[db_name] = {};
Then JSON.stringify will work.
Example:
const dbs_list = {};
let db_name;
let random = Math.floor(Math.random() * 10000);
db_name = "mysql" + random;
dbs_list[db_name] = {};
++random;
db_name = "mysql" + random;
dbs_list[db_name] = {};
console.log(JSON.stringify(dbs_list));
If for some reason you wanted to keep the properties non-enumerable, you could get an array of their names using Object.getOwnPropertyNames, then loop through that. But I don't see any reason for these to be non-enumerable properties.
2 Comments
defineProperty wasn't even added until ES5 in 2009. Until then, assignment (obj[expression] = value or obj.name = value;) was the only way to add properties to an object that already existed.