在我的应用程序中,我在另一个内部编写了一个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
答案 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?
希望这有帮助!