Rails + Mongoid - Do not return nil values ​​in JSON

I have many optional fields in Mongoid, for example:

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

If I return json to this model, only one of them is full, I get null values ​​in all other fields. How to remove these fields?

My model has nested attributes, which means that null values ​​can be at several levels.

Explanations:

I need a way to remove empty fields from a json representation of a model, including empty fields in all nested attributes.

Code example :

 1.9.3-p0 :005 > u=Muse.new(:key=>'ram').to_json => "{\"_id\":\"4f1ced749c2ee4219d000003\",\"element\":null,\"key\":\"ram\",\"rect\":null}" 
+4
source share
4 answers

By default, mongoid has the ability to delete empty fields. If you mongoid some fields are empty, mongoid will delete them when pasting.

in the example below i skipped 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"}" 

and it works great. But if you put a zero value in the field

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

This is inserted. I assume that it is the problem in your code. This way you can get around this by converting the JSON hash representation using as_json and removing the nil fields

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

But to go to the inner levels, you cannot use as_json . check the code below

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

Now you see that the dummy inside the built-in document house is still with zero. so my best advice is: do not put zero values ​​in dB at all . To do this, before_save for your models (also built-in) and delete the empty fields.

I will also show you how to remove nil fields from nested objects. Use it if there is no other way

We can use the attributes the mongoid model to get a hash representation of the object, including nested levels

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

and you must find out if there is a hash inside the mongoid object, if it is, we must use reject! {|k,v| v.nil?} reject! {|k,v| v.nil?} reject! {|k,v| v.nil?} reject! {|k,v| v.nil?} reject! {|k,v| v.nil?} reject! {|k,v| v.nil?} reject! {|k,v| v.nil?} reject! {|k,v| v.nil?} reject! {|k,v| v.nil?} to this hash too

collect everything

 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 

and call it with the attributes of the model,

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

It's all. Hope help

+5
source

If you are just trying to remove field keys with null values ​​from the query results before sending JSON to, say, the browser, you can simply do this (works in my case):

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

As far as I know, there is no such feature in the Mongoid. My suggestion would be to go with one of the API generators, and then:

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

https://github.com/nesquena/rabl

or

https://github.com/rails/jbuilder

+1
source

This is easy to do if you use active_model_serializers (check this Railscast for quick input).

In your use case, you can write muse_serializer.rb , which looks like this:

 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 

This will return all non-empty fields present in the current Muse object.

0
source

Source: https://habr.com/ru/post/1389313/


All Articles