toJSON view model overrides not being reflected af

2019-09-02 15:54发布

问题:

I have a deep object graph from the server which I am representing with a Knockout view model structure which omits various unnecessary properties at each level but preserves the basic hierarchy.

I'm using the Knockout mapping plugin in both directions. At each view model level below the root, the "constructor" of the current view model accepts its parent view model to keep as a reference, plus the part of the original data necessary to construct itself with. It then creates a new set of mapping options to create its own children.

I've created a heavily simplified fiddle which illustrates this:

http://jsfiddle.net/tqPtG/17/

There is a lot of heavy readonly metadata which I need from the server on retrieval, but should be omitted when I post the graph back as JSON. I've been using the toJSON prototype method at each level to cull what I don't need, and this was working beautifully at one point but has now stopped working.

Locally, it appears that my toJSON overrides do not even fire (based on alerts and console logs), but in this fiddle, they do fire, but the final object still contains the deleted property "child". I can see it being removed by the toJSON method but after the root unmapping it is still there and shown in the alert.

So, 2 questions - what would cause my toJSON overrides to not fire locally, and where is my misunderstanding of the unmapping logic in the simplified fiddle?

Many thanks in advance.

回答1:

A couple of things are going on here:

  • your toJSON function is getting called, but not as part of the ko.mapping.toJSON call. The mapping plugin does a stringify as part of determining a key for objects.
  • ko.mapping.toJSON creates a plan copy of the object and at that point it is no longer an instance of ParentViewModel. Then, when it stringifies the object, it will have no reason to run your toJSON function.

The call to ko.mapping.toJSON does support a second argument for options. You could pass { ignore: ['child'] } in as this argument like: http://jsfiddle.net/rniemeyer/4kHC2/