Rails + Mongoid - 不要在JSON中返回nil值

问题描述 投票:5回答:4

我在Mongoid中有很多可选字段,例如:

  field :key, type: String             
  field :element, type: String         
  field :rect, type: Array             

如果我返回这个模型的json,其中只有一个填充,我会在所有其他字段上获得null值。我该如何删除这些字段?

我的模型有嵌套属性,这意味着空值可以在几个级别上。

澄清:

我需要一种方法从模型的json表示中删除空字段,包括所有嵌套属性中的空字段。

代码示例:

1.9.3-p0 :005 > u=Muse.new(:key=>'ram').to_json
 => "{\"_id\":\"4f1ced749c2ee4219d000003\",\"element\":null,\"key\":\"ram\",\"rect\":null}" 
ruby-on-rails ruby mongodb mongoid
4个回答
7
投票

默认情况下,mongoid可以删除空字段。如果你让一些字段为空,mongoid将在插入时删除它们。

在下面的例子中,我省略了fields元素&rect

class User
  include Mongoid::Document

    field :key, type: String             
    field :element, type: String         
    field :rect, type: Array       

    embeds_one :home  
end
>> u=User.new(:key=>'ram').to_json
=> "{"_id":"4f1c3722b356f82e4a000001","_type":"key":"ram"}"

它完美无缺。但是如果你在场上放一个零值

>> u=User.new(:key=>'ram',:element=>nil).to_json
=> "{"_id":"4f1c3722b356f82e4a000001","_type":"User","key":"ram","element":null}"

它被插入。我认为这是你代码中的确切问题。因此,您可以通过使用as_json转换JSON哈希表示并删除nil字段来解决此问题

x=u.as_json.reject! {|k,v| v.nil?}
=> "{"_id":"4f1c3722b356f82e4a000001","_type":"User","key":"ram"}"

但要进入内层,你不能使用as_json。检查以下代码

  >>h=Home.new(:address=>'xxxx',:dummy=>nil)
  >>u.home = h 
  >>x=u.as_json.reject! {|k,v| v.nil?}
  =>{"_id"=>BSON::ObjectId('4f1c39b4b356f82e4a000003'), "_type"=>"User","key":"ram","home"=>#<Home _id: 4f1c3c5db356f82e4a000004,address:'xxxx' , dummy: nil >}

现在你看到嵌入式doc house里面的字段虚拟仍然是零。所以我最好的建议是不要将db值设为db。为此,在模型上放置一个before_save回调(也嵌入)并删除空字段。

另外,我将向您展示如何从嵌套对象中删除空字段。如果没有其他办法,请使用它

我们可以使用mongoid模型的attributes来获取对象的哈希表示,包括嵌套级别

x=u.attributes
=> {"_id"=>BSON::ObjectId4f1c39b4b356f82e4a000003,"key"=>"ram","element"=>nil,"home"=>{"address"=>"xxxx", "_id"=>BSON::ObjectId4f1c3c5db356f82e4a000004,"dummy"=>nil}}

而且你必须找到mongoid对象里面有任何哈希,如果有的话,我们也必须在那个Hash上使用reject! {|k,v| v.nil?}

整理所有

def to_json(obj)
     obj.reject! {|k,v| v.nil?}
     obj.find_all {|x| x[1].class==BSON::OrderedHash}.each do |arr| 
           obj[arr[0]] = to_json(arr[1])    
     end
     obj     
end

并使用模型的属性调用它,

 >> to_json u.attributes
 => {"_id"=>BSON::ObjectId4f1c39b4b356f82e4a000003,"key"=>"ram","home"=>{"address"=>"xxxx", "_id"=>BSON::ObjectId4f1c3c5db356f82e4a000004}}

就这样。希望能帮助到你


2
投票

如果你只是想在向浏览器发送JSON之前从查询结果中删除带有nil值的字段键,你可以简单地执行此操作(在我的情况下适用):

doc = Model.all.entries.map {|d| d.as_document}
respond_width(doc)

1
投票

据我所知,Mongoid iself中没有这样的功能。我的建议是使用其中一个API生成器:

http://fabrik42.github.com/acts_as_api/

https://github.com/nesquena/rabl

要么

https://github.com/rails/jbuilder


0
投票

如果你正在使用active_model_serializers这很容易做(请查看this Railscast快速介绍)。

对于您的用例,您可以编写如下所示的muse_serializer.rb

class MuseSerializer < ActiveModel::Serializer
  def attributes
    muse = super
    object.attributes.each do |attr|
      muse[attr[0]] = attr[1]
    end
    muse.delete('_id') #in case you want to exclude the _id field
    muse
  end
end

这将返回当前Muse对象中存在的所有非空字段。

© www.soinside.com 2019 - 2024. All rights reserved.