'Have to_json return a mongoid as a string

In my Rails API, I'd like a Mongo object to return as a JSON string with the Mongo UID as an "id" property rather than as an "_id" object.

I want my API to return the following JSON:

{
    "id": "536268a06d2d7019ba000000",
    "created_at": null,
}

Instead of:

{
    "_id": {
        "$oid": "536268a06d2d7019ba000000"
    },
    "created_at": null,
}

My model code is:

class Profile
  include Mongoid::Document
  field :name, type: String

  def to_json(options={})
    #what to do here?
    # options[:except] ||= :_id  #%w(_id)
    super(options)
  end
end


Solution 1:[1]

You can monkey patch Moped::BSON::ObjectId:

module Moped
  module BSON
    class ObjectId   
      def to_json(*)
        to_s.to_json
      end
      def as_json(*)
        to_s.as_json
      end
    end
  end
end

to take care of the $oid stuff and then Mongoid::Document to convert _id to id:

module Mongoid
  module Document
    def serializable_hash(options = nil)
      h = super(options)
      h['id'] = h.delete('_id') if(h.has_key?('_id'))
      h
    end
  end
end

That will make all of your Mongoid objects behave sensibly.

Solution 2:[2]

For guys using Mongoid 4+ use this,

module BSON
  class ObjectId
    alias :to_json :to_s
    alias :as_json :to_s
  end
end

Reference

Solution 3:[3]

You can change the data in as_json method, while data is a hash:

class Profile
  include Mongoid::Document
  field :name, type: String

   def as_json(*args)
    res = super
    res["id"] = res.delete("_id").to_s
    res
  end
end

p = Profile.new
p.to_json

result:

{
    "id": "536268a06d2d7019ba000000",
    ...
}

Solution 4:[4]

Use for example:

user = collection.find_one(...)
user['_id'] = user['_id'].to_s
user.to_json

this return

{
    "_id": "54ed1e9896188813b0000001"
}

Solution 5:[5]

class Profile
  include Mongoid::Document
  field :name, type: String
  def to_json
    as_json(except: :_id).merge(id: id.to_s).to_json
  end
end

Solution 6:[6]

If you don't want to change default behavior of MongoId, just convert result of as_json.

profile.as_json.map{|k,v| [k, v.is_a?(BSON::ObjectId) ? v.to_s : v]}.to_h

Also, this convert other BSON::ObjectId like user_id.

Solution 7:[7]

# config/initializers/mongoid.rb

# convert object key "_id" to "id" and remove "_id" from displayed attributes on mongoid documents when represented as JSON
module Mongoid
  module Document
    def as_json(options={})
      attrs = super(options)
      id = {id: attrs["_id"].to_s}
      attrs.delete("_id")
      id.merge(attrs)
    end
  end
end

# converts object ids from BSON type object id to plain old string
module BSON
  class ObjectId
    alias :to_json :to_s
    alias :as_json :to_s
  end
end

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 mu is too short
Solution 2 Ronak Jain
Solution 3
Solution 4 Juan Labrador
Solution 5
Solution 6 hiroshi
Solution 7 Hackeron