首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我可以将一个EJSON对象嵌入到另一个EJSON对象中吗?

我可以将一个EJSON对象嵌入到另一个EJSON对象中吗?
EN

Stack Overflow用户
提问于 2013-07-12 00:32:53
回答 1查看 628关注 0票数 4

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

那么,有没有办法将一个EJSON对象嵌入到另一个EJSON对象中呢?也许我的代码中有一个缺陷?这只是一个坏主意吗?我可以让class A在它的constructor中自己实例化class B项,但是看起来EJSON应该能够处理这个问题。如果你认为这是一个bug,我很乐意在github上提交一个问题,但我想我应该先在这里检查一下。

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

如果这个问题很难理解,请让我知道,我会试着澄清。

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

代码语言:javascript
复制
@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")})
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-08-04 13:47:13

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

假设我们将要通过网络传递您的外部类的一个实例(例如作为方法调用中的参数)。

代码语言:javascript
复制
myOuter = new Outer({innerHere: new Inner('inner value')});

Meteor将遵循与以下类似的步骤:

代码语言:javascript
复制
EJSON.stringify(myOuter) => 
  var jsonValue = EJSON.toJSONValue(myOuter);
  var json = JSON.stringify(jsonValue);

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

代码语言:javascript
复制
{
  $type: 'Outer',
  $value: {
    innerHere: {
      value: 'inner value'
    }
  }
}

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

代码语言:javascript
复制
"{"$type":"Outer","$value":{"value":{"innerHere":{"value":"inner value"}}}}"

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

代码语言:javascript
复制
Outer.prototype.toJSONValue = function () {
  return {
    value: EJSON.toJSONValue(this.value)
  };
};

现在假设我们创建一个新的外部实例,如下所示:

代码语言:javascript
复制
myOuter = new Outer(new Inner('inner value'));

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

代码语言:javascript
复制
{
  $type: 'Outer',
  $value: {
    value: {
      $type: 'Inner',
      $value: {
        value: 'inner value'
      }
    }
  }
}

通过网络发送的json字符串如下所示:

代码语言:javascript
复制
"{"$type":"Outer","$value":{"value":{"$type":"Inner","$value":{"value":"inner value"}}}}"

好了,那么现在我们的fromJSONValue函数中发生了什么?我们将得到一个与toJSONValue返回的对象相似的对象。因此,在将每个已知为自定义类型的属性传递给外部的构造函数之前,我们需要对这些属性调用EJSON.fromJSONValue。在此示例中,您可以执行以下操作:

代码语言:javascript
复制
EJSON.addType('Outer', function (jsonValue) {
  var inner = EJSON.fromJSONValue(jsonValue.value);
  return new Outer(inner);
});

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

代码语言:javascript
复制
var serialized = EJSON.stringify(myOuter);
var deserialized = EJSON.parse(serialized); // is the resulting object what you expect?

希望这能有所帮助!

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17598811

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档