meteor - Can I embed an EJSON object inside another EJSON object? -


in app, composed 1 coffeescript class inside (an instance of class a includes array of objects have instances of class b 1 of properties). discovered cmather's video ejson , thought cool use objects. however, meteor doesn't seem deal correctly ejson objects inside other ejson objects - class a can saved datastore and, when queried, comes class a, class b ends coming collection object rather class b instance. when ran test code, embedded ejson objects seemed work @ first (after initial collection.insert()), returned plain objects or incorrectly structured objects after refreshing browser. theory there mismatch in behavior of minimongo , server-side mongo, there other causes.

so, there way embed 1 ejson object inside another? perhaps there flaw in code? bad idea? have class a instantiate class b items in constructor, seems ejson ought able handle this. if think bug, i'll happy submit issue on github, thought i'd check here first.

if need code try out, can try code below, sets 2 identical classes, 1 called inner, , 1 called outer, , creates instance of of outer called outer contains instance of inner property innerhere. in console, type testcollection.insert({outerhere: outer}. now, testcollection.findone() may give object object's innerhere property proper instance of inner, if refresh browser, same command may return different.

if question hard follow, let me know, , i'll try clarify.

the code set (just make .coffee file in new project's root):

@testcollection = new meteor.collection("test")  class @outer   constructor: (value) ->     @value = value   clone: ->     new outer(@value)   equals: (other) ->     _.isequal(@, other)   typename: ->     "outer"   tojsonvalue: ->     value: @value   ejson.addtype("outer", (value)->   new outer(value) )  class @inner   constructor: (value) ->     @value = value   clone: ->     new inner(@value)   equals: (other) ->     _.isequal(@, other)   typename: ->     "inner"   tojsonvalue: ->     value: @value   ejson.addtype("inner", (value)->   new inner(value) )  @outer = new outer({innerhere: new inner ("inner value")}) 

when ejson calls tojsonvalue of outer type, doesn't recurse result automatically detect inner types. likewise, in fromjsonvalue (the function you're passing ejson.addtype method), you're getting json value object (the result of whatever tojsonvalue returns) , that. better understand conversion process, let's walk through example given classes.

let's we're pass instance of outer class on wire (like parameter in method call).

myouter = new outer({innerhere: new inner('inner value')}); 

meteor follow steps similar to:

ejson.stringify(myouter) =>    var jsonvalue = ejson.tojsonvalue(myouter);   var json = json.stringify(jsonvalue); 

the call ejson.tojsonvalue creates new object $type , $value property. $value property's value result of calling tojsonvalue on object. jsonvalue object looks this:

{   $type: 'outer',   $value: {     innerhere: {       value: 'inner value'     }   } } 

calling json.stringify(jsonvalue) results in json string looks this:

"{"$type":"outer","$value":{"value":{"innerhere":{"value":"inner value"}}}}" 

if want innerhere property ejson type, need call ejson.tojsonvalue on object (from outer's tojsonvalue method). example (in js):

outer.prototype.tojsonvalue = function () {   return {     value: ejson.tojsonvalue(this.value)   }; }; 

now lets create new instance of outer this:

myouter = new outer(new inner('inner value')); 

and call ejson.tojsonvalue(myouter):

{   $type: 'outer',   $value: {     value: {       $type: 'inner',       $value: {         value: 'inner value'       }     }   } } 

and resulting json string sent on wire looks this:

"{"$type":"outer","$value":{"value":{"$type":"inner","$value":{"value":"inner value"}}}}" 

okay happens in our fromjsonvalue function? we're going object looks similar whatever tojsonvalue returned. need call ejson.fromjsonvalue on each of properties know custom types before passing them constructor of outer. in example might this:

ejson.addtype('outer', function (jsonvalue) {   var inner = ejson.fromjsonvalue(jsonvalue.value);   return new outer(inner); }); 

the 2 methods can use test serialization , deserialization are:

var serialized = ejson.stringify(myouter); var deserialized = ejson.parse(serialized); // resulting object expect? 

hope helps!


Comments