Format of BSONObjectID as JSON

886 views
Skip to first unread message

Stephen Gordon

unread,
Dec 11, 2012, 5:49:12 PM12/11/12
to reacti...@googlegroups.com
Just started playing with reactivemongo in a simple API I am writing.

case class Foo(
  id: Option[BSONObjectID],
  bar: String)

object Foo(
  // implement implict's which extend BSONReader and BSONWriter as in tutorial docs...
)

Now in my controller, 

if I do something simple like:

/...
val query = BSONDocument("bar" -> BSONString("coffee"))
collection.find(query).toList.map { results =>
  Ok(results.foldLeft(JsArray(List()))( (obj, res) => obj ++ Json.arr(res) ))

The result is as expected, a JSON array containing all the objects found that matched the query.  However I have a couple questions, 

First, the result has the JSON in a format which is not desirable, the "_id" field is not just the string representation but rather an object itself:
{
_id
{
  • $oid"50a2c992eca75db398b70439"
},
bar: "coffee"
}

I would rather rename the _id field and only display the string like:  
{
coffeeId: "50a2c992eca75db398b70439"
bar: "coffee"
}

How can I effect how the BSON is mapped to JSON?  What if I didn't even want the objectId field (or any other field for the matter) to be displayed?

I am pretty new to this, and VERY new to mongo / scala 2.10 / play 2.1 I apologize if this is a trivial question or misplaced in this group.

-- Steve


Pascal Voitot Dev

unread,
Dec 11, 2012, 6:35:24 PM12/11/12
to reacti...@googlegroups.com
You can rewrite the Writes[BSONObjectId] or use Json transformers designed for transforming JSON to JSON

For ex:
scala> __.json.update( (__ \ 'id).json.copyFrom( (__ \ 'id \ '$oid).json.pick ) )
res1: play.api.libs.json.Reads[play.api.libs.json.JsObject] = play.api.libs.json.Reads$$anon$8@20de0ee

scala> res1.reads( Json.obj( "id" -> Json.obj("$oid" -> "12345") ) )
res2: play.api.libs.json.JsResult[play.api.libs.json.JsObject] = JsSuccess({"id":"12345"},/id/$oid)

Json transformers are explained in this article: http://mandubian.com/2012/10/29/unveiling-play-2-dot-1-json-api-part3-json-transformers/ (which will be in Play2.1 doc soon)

Best Regards
Pascal

On Tue, Dec 11, 2012 at 11:49 PM, Stephen Gordon <mailstuf...@gmail.com> wrote:
which

Mehmet Ali GÖZAYDIN

unread,
Dec 20, 2012, 10:33:57 AM12/20/12
to reacti...@googlegroups.com
Hi,

 Thanks for answer. Just a little fix, your transforming should be:

 __.json.update( (__ \ 'id).json.copyFrom( (__ \ '_id \ '$oid).json.pick ) )

I tried to solve problem like an hour just becuse copy paste code :/

Pascal Voitot Dev

unread,
Dec 20, 2012, 10:36:44 AM12/20/12
to reacti...@googlegroups.com
I don't see the difference... Am I blind? :D



--
 
 

Mehmet Ali GÖZAYDIN

unread,
Dec 20, 2012, 11:23:31 AM12/20/12
to reacti...@googlegroups.com
__.json.update( (__ \ 'id).json.copyFrom( (__ \ '_id \ '$oid).json.pick ) )
                                                                   ^
                                                         This little red underscore :)

Pascal Voitot Dev

unread,
Dec 20, 2012, 11:26:53 AM12/20/12
to reacti...@googlegroups.com
Ooooh sorry about that :D
I find this "_id" is a pain in Mongo:D


--
 
 

Mehmet Ali GÖZAYDIN

unread,
Dec 20, 2012, 1:12:04 PM12/20/12
to reacti...@googlegroups.com
I couldn't agree more :)

David Bouyssié

unread,
Feb 18, 2014, 11:03:51 AM2/18/14
to reacti...@googlegroups.com
I prefer the use of the following macro :

implicit object BSONObjectIDFormat extends Format[BSONObjectID] {
    def writes(objectId: BSONObjectID): JsValue = JsString(objectId.stringify)
    def reads(json: JsValue): JsResult[BSONObjectID] = json match {
      case JsString(x) => {
        val maybeOID: Try[BSONObjectID] = BSONObjectID.parse(x)
        if(maybeOID.isSuccess) JsSuccess(maybeOID.get) else {
          JsError("Expected BSONObjectID as JsString")
        }
      }
      case _ => JsError("Expected BSONObjectID as JsString")
    }
  }

Reply all
Reply to author
Forward
0 new messages