0

When trying to insert a MongoDBObject that contains a JsNumber

val obj: DBObject = getDbObj // contains a "JsNumber()"
collection.insert(obj)

the following error occurs:

[error] play - Cannot invoke the action, eventually got an error: java.lang.IllegalArgumentException: can't serialize class scala.math.BigDecimal

I tried to replace the JsNumber with an Int, but I got the same error.

EDIT

Error can be reproduced via this test code. Full code in scalatest (https://gist.github.com/kman007us/6617735)

val collection = MongoConnection()("test")("test")
val obj: JsValue = Json.obj("age" -> JsNumber(100))
val q = MongoDBObject("name" -> obj)
collection.insert(q)
Kevin Meredith
  • 41,036
  • 63
  • 209
  • 384

2 Answers2

2

There are no registered handlers for Plays JSON implementation - you could add handlers to automatically translate plays Js Types to BSON types. However, that wont handle mongodb extended json which has a special structure dealing with non native json types eg: date and objectid translations.

An example of using this is:

import com.mongodb.util.JSON
val obj: JsValue = Json.obj("age" -> JsNumber(100))
val doc: DBObject = JSON.parse(obj.toString).asInstanceOf[DBObject]

For an example of a bson transformer see the joda time transformer.

Ross
  • 17,861
  • 2
  • 55
  • 73
  • Thanks - that worked. However, is the `asInstanceOf[DBObject]` bad practice since a run-time exception could occur? – Kevin Meredith Sep 19 '13 at 20:23
  • The returned value is either a DBObject, if the string is a JSON object or array or a boxed primitive value according to the following mapping. So theres room for a runtime exception especially where data is from an untrusted source. – Ross Sep 19 '13 at 20:59
1

It seems that casbah driver isn't compatible with Plays's JSON implementation. If I look through the cashbah code than it seems that you must use a set of MongoDBObject objects to build your query. The following snippet should work.

val collection = MongoConnection()("test")("test")
val obj = MongoDBObject("age" -> 100)
val q = MongoDBObject("name" -> obj)
collection.insert(q)

If you need the compatibility with Play's JSON implementation then use ReactiveMongo and Play-ReactiveMongo.

Edit

Maybe this Gist can help to convert JsValue objects into MongoDBObject objects.

akkie
  • 2,523
  • 1
  • 20
  • 34