Reputation: 312
In sending objects back and forth between JS (TypeScript actually) and .NET w/ protobuf.js I would like to decorate the JS objects w/ fields only meaningful at runtime (e.g. WebGL context, handles, etc.). Adding a new dynamic field is straightforward:
ReceivedObject.RuntimeField = new RuntimeField();
However, when serializing back up to the server protobuf.js discovers the new field and throws an exception.
I have found I can hack around this by adding the three lines below directly to protobuf.js:
MessagePrototype.set = function (keyOrObj, value, noAssert) {
if (keyOrObj && typeof keyOrObj === 'object') {
noAssert = value;
for (var ikey in keyOrObj)
if (keyOrObj.hasOwnProperty(ikey) && typeof (value = keyOrObj[ikey]) !== 'undefined') {
if (ikey == "RuntimeField") { // added
continue; // added
} // added
this.$set(ikey, value, noAssert);
}
return this;
}
...
}
This is of course not very maintainable. Is there a better approach? The object hierarchy is rich and deep so I'd like to avoid approaches involving wholesale copying of 100s of fields to/from custom JS-side objects.
Thanks for any suggestions.
Upvotes: 3
Views: 871
Reputation: 251072
I have created a short example for you. You can solve this problem using Object.defineProperty
to add a non-enumerable property (this won't show up when you use for (var key in obj)
.
In the example below, the first
property is enumerable (and will appear in the console window along with the name
property). The second
property is not enumerable, so it won't appear in the console window.
Using this technique, you could add properties that won't be picked up in your for
loop.
var obj = {
name: 'Steve'
};
Object.defineProperty(obj, 'first', {
enumerable: true,
value: 'example'
});
Object.defineProperty(obj, 'second', {
enumerable: false,
value: 'example'
});
for (var key in obj) {
if (obj.hasOwnProperty(key)
&& typeof (value = obj[key]) !== 'undefined') {
console.log(key);
}
}
So to tie this back to your specific question, you could use...
Object.defineProperty(ReceivedObject, 'RuntimeField', {
enumerable: false,
value: new RuntimeField()
});
Upvotes: 2