I'm findign that ko.toJSON is creating some unwanted stuff like:
copiedProperties destroy
{"test":1,"AppStart":true,"requestedDateFormat":"YYYY-MM-DD","__ko_mapping__":{"ignore":[],"include":["_destroy"],"copy":[],"observe":[],"mappedProperties":{"test":true,"AppStart":true,"requestedDateFormat":true},"copiedProperties":{}}}
whats the point of these? can I remove them by default?
If you are using the KO mapping plugin you should use the plugin's conversion methods e.g.
ko.mapping.toJSON
and ko.mapping.toJS
instead of the built in ko.toJSON
and ko.toJS
.
Because the mapping version of the methods will take of the additional properties which by the way are used internally by the plugin itself.
Demo JSFiddle.
If your model is a 'hybrid' model that hasn't completely been created using the mapping plugin then using ko.mapping.toJSON
may not remove the __ko_mapping__
properties you're expecting.
By 'hybrid' model I mean one you've created as a normal object and then mapped only portions into it with the mapping plugin.
The easiest solution is to add the following to each 'class' that is ending up with the unwanted properties. This will remove it whether you use mapping.toJSON
or ko.toJSON
.
Product.prototype.toJSON = function()
{
var copy = ko.toJS(this);
delete (copy.__ko_mapping__);
return copy;
}
This method is described in Controlling How an Object Is Converted to JSON although not in connection to the mapping plugin.
Here's some JSON that ended up with unwanted mapping when it was serialized (even with ko.mapping.toJSON
).
I just added the above code to the 'product' class (I'm using typescript so I'm calling them classes).
{"sku":"3007","total":0,"desc":"Description","qty":0,"each":null,"dirty":false,"removePending":false,"editableQty":0,"itemUpdating":false,"__ko_mapping__":{"ignore":[],"include":["_destroy"],"copy":[],"observe":[],"mappedProperties":{"sku":true,"qty":true},"copiedProperties":{}}},{"sku":"3008","total":0,"desc":"Description","qty":0,"each":null,"dirty":false,"removePending":false,"editableQty":0,"itemUpdating":false,"__ko_mapping__":{"ignore":[],"include":["_destroy"],"copy":[],"observe":[],"mappedProperties":{"sku":true,"qty":true},"copiedProperties":{}}},
Afterwards I got this much cleaner JSON. I'm now going to go back and delete(copy.removePending)
and delete(copy.itemUpdating)
which are view model only.
{"sku":"3007","total":0,"desc":"Description","qty":0,"each":null,"dirty":false,"removePending":false,"editableQty":0,"itemUpdating":false},{"sku":"3008","total":0,"desc":"Description","qty":0,"each":null,"dirty":false,"removePending":false,"editableQty":0,"itemUpdating":false},
Also please note that calling the mapping version of toJSON
internally just calls JSON.stringify(ko.mapping.toJS(object))
. In other words ko.mapping.toJSON
is a convenience function and does not do its own stringification.
// from mapping source code
exports.toJSON = function (rootObject, options)
{
var plainJavaScriptObject = exports.toJS(rootObject, options);
return ko.utils.stringifyJson(plainJavaScriptObject);
};
// from main knockout source code for `ko.utils`
stringifyJson: function (data, replacer, space) { // replacer and space are optional
if (!JSON || !JSON.stringify)
throw new Error("Cannot find JSON.stringify(). Some browsers (e.g., IE < 8) don't support it natively, but you can overcome this by adding a script reference to json2.js, downloadable from http://www.json.org/json2.js");
return JSON.stringify(ko.utils.unwrapObservable(data), replacer, space);
},
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