我可以在另一个EJSON对象中嵌入一个EJSON对象吗?

时间:2013-07-11 16:32:53

标签: meteor

在我的应用程序中,我在另一个内部编写了一个coffeescript类(class A的实例包含一个对象数组,这些对象的实例为class B作为其属性之一)。然后我发现cmather's video about EJSON并认为将它与我的对象一起使用会很酷。但是,Meteor似乎没有正确处理其他EJSON对象中的EJSON对象 - class A可以保存到数据存储区,并且在查询时返回class A,但{{{} 1}}最终作为class B而不是Object实例从集合中返回。当我运行一些测试代码时,嵌入式EJSON对象似乎首先工作(在初始class B之后),但是在刷新浏览器之后它返回了普通的collection.insert()甚至是错误的结构化对象。我的理论是,minimongo和服务器端mongo的行为存在一些不匹配,但可能还有其他原因。

那么,有没有办法将一个EJSON对象嵌入另一个?也许我的代码存在缺陷?这只是一个坏主意吗?我可以让Object在其class A中实例化class B项目,但似乎EJSON应该能够处理这个问题。如果您认为这是一个错误,我会很乐意在github上提交一个问题,但我想先在这里查看。

如果您需要代码来尝试这一点,您可以尝试下面的代码,它设置两个基本相同的类,一个名为constructor,一个名为Inner,并创建一个实例名为Outer的{​​{1}}包含Outer的实例作为属性outer。在控制台中,键入Inner。现在,innerHere可能会为您提供一个对象,其中对象的testCollection.insert({outerHere: outer}属性是testCollection.findOne()的正确实例,但是如果刷新浏览器,则相同的命令可能会返回不同的内容。

如果这个问题难以理解,请告诉我,我会尽力澄清。

设置此代码的代码(只需在新项目的根目录中创建一个innerHere文件):

Inner

1 个答案:

答案 0 :(得分:4)

当EJSON调用您的Outer类型的JSONValue时,它不会递归到结果中以自动检测内部类型。同样,在fromJSONValue(您传递给EJSON.addType方法的函数)中,您将获得一个JSON值对象(任何toJSONValue返回的结果),并由您自己来做。为了更好地理解转换过程,让我们看一下给出类的示例。

假设我们将要通过线路传递您的Outer类的实例(就像作为方法调用中的参数一样)。

myOuter = new Outer({innerHere: new Inner('inner value')});

Meteor将遵循类似于以下步骤:

EJSON.stringify(myOuter) => 
  var jsonValue = EJSON.toJSONValue(myOuter);
  var json = JSON.stringify(jsonValue);

对EJSON.toJSONValue的调用会创建一个带有$ type和$ value属性的新对象。 $ value属性的值是在对象上调用toJSONValue的结果。所以jsonValue是一个看起来像这样的对象:

{
  $type: 'Outer',
  $value: {
    innerHere: {
      value: 'inner value'
    }
  }
}

调用JSON.stringify(jsonValue)会产生一个如下所示的JSON字符串:

"{"$type":"Outer","$value":{"value":{"innerHere":{"value":"inner value"}}}}"

如果您希望innerHere属性为EJSON类型,我们还需要在该对象上调用EJSON.toJSONValue(从Outer的toJSONValue方法)。例如(在js中):

Outer.prototype.toJSONValue = function () {
  return {
    value: EJSON.toJSONValue(this.value)
  };
};

现在我们假设我们像这样创建一个新的Outer实例:

myOuter = new Outer(new Inner('inner value'));

然后我们调用EJSON.toJSONValue(myOuter):

{
  $type: 'Outer',
  $value: {
    value: {
      $type: 'Inner',
      $value: {
        value: 'inner value'
      }
    }
  }
}

通过线路发送的结果json字符串如下所示:

"{"$type":"Outer","$value":{"value":{"$type":"Inner","$value":{"value":"inner value"}}}}"

好的,现在我们的fromJSONValue函数会发生什么?我们将得到一个类似于返回的任何toJSONValue的对象。因此,在将它们传递给Outer的构造函数之前,我们需要在我们知道的每个属性上调用EJSON.fromJSONValue作为自定义类型。在此示例中,您可以执行此操作:

EJSON.addType('Outer', function (jsonValue) {
  var inner = EJSON.fromJSONValue(jsonValue.value);
  return new Outer(inner);
});

可用于测试序列化和反序列化的两种方法是:

var serialized = EJSON.stringify(myOuter);
var deserialized = EJSON.parse(serialized); // is the resulting object what you expect?

希望这有帮助!