2012-01-04 24 views
4

回到零值,我有很多Mongoid可選字段,如:的Rails + Mongoid - 不要在JSON

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}" 
+1

一些示例數據/預期的輸入/輸出將在這裏有所幫助 – Yule 2012-01-04 17:00:26

+0

在模型上調用to_json時,它可以正常工作。 JSON對象沒有任何空的字段?你正在使用哪個版本的mongoid?並調用your_doc_obj.to_json它返回null? – RameshVel 2012-01-22 16:16:27

+0

它有空字段。這個例子中只有一個字段是填充的,另一個是空值,我想將它們去掉。我也想刪除其他字段(但那些我將剝離:attr_protected) – CamelCamelCamel 2012-01-22 16:24:40

回答

5

默認情況下mongoid有權刪除空字段的能力。如果你讓一些字段爲空,mongoid會在插入時刪除它們。

在下面的示例中

,我離開了字段元件& 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"}" 

和它完美。但是,如果你在該字段中輸入零值,那麼它將被插入。假設這是你代碼中的確切問題。所以,你可以解決此通過轉換使用JSON as_json哈希表示並取出零領域

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 >} 

現在你看到嵌入文檔屋內場虛擬仍與零。所以我最好的建議是不要把db的零值全部寫入。要做到這一點,在您的模型上嵌入before_save回調(嵌入),並刪除空字段。

另外我會告訴你如何從嵌套對象中刪除零字段。使用它,如果沒有其他的辦法

我們可以用mongoid模型attributes來獲取對象的散列表示包括嵌套級別

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

,你必須發現有任何哈希mongoid內對象,如果有,我們必須使用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}} 

那就是所有。希望它有幫助

+0

謝謝!這聽起來是合理的,遞歸哈希thingy是我最終做的,但它很爛,我提出了尋找另一種方式的賞金。我明天會測試它,但是這行看起來不正確:「」{「_id」:「4f1c3722b356f82e4a000001」,「_ type」:「key」,「fname」:「ram」}「」 - 什麼是fname? – CamelCamelCamel 2012-01-22 19:21:21

+0

@myxospsm,這是一個錯字...我混合了我的原始測試數據:( – RameshVel 2012-01-22 20:25:44

+0

對不起,它不起作用。Mongoid自動將空值放入模型中,也許我會使用動態字段。問題) – CamelCamelCamel 2012-01-23 05:26:53

1

據我所知,在Mongoid自己沒有這樣的功能。 我的建議是去與API發電機中的一個,那麼:

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

https://github.com/nesquena/rabl

https://github.com/rails/jbuilder

+0

我已經看過acts_as_api之前,但我不知道它是如何解決null清除問題 – CamelCamelCamel 2012-01-23 04:56:26

+0

你基本上有一些業務規則來編寫JSON響應所以,除非你想手工編碼(這當然是可能的),你最好使用這些解決方案之一,恕我直言。 – Roman 2012-01-23 19:07:42

2

如果你只是想刪除與零場鍵在向瀏覽器發送JSON之前查詢結果中的值,您可以簡單地執行此操作(適用於我的情況):

doc = Model.all.entries.map {|d| d.as_document} 
respond_width(doc) 
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 

這將返回存在於當前繆斯對象的所有非空字段。