0

In our project we are using Scala and Reactivemongo. (I'm very new to both) When you print to the console a "pretty" Bson, it looks like this:

{  _id: BSONObjectID("52b006fe0100000100d47242"),
desc: BSONString({"_id:"BSONObjectID(52af03a5010000010036194d),"desc:"BSONString(www.foo.com"hits),"domains:"["0:"BSONString(www.foo.com)"],"func:"BSONString(Count),"maxr:"BSONInteger(5),"props:"["]"} hits),
domains: [
0: BSONString(jsonString)
],
func: BSONString(Count),
maxr: BSONInteger(5),
props: [
]
}

I need to be able to parse it back from the console into a corosponding Case Class.

Any help please?

Shany Tooper
  • 3
  • 1
  • 2

3 Answers3

1

taken from typesafe's activator template, you can simply use Json.format as an implicit val in the case class's companion object (ReactiveMongo 0.9, scala 2.10.2). example:

package models

import play.api.libs.json.Json
import reactivemongo.bson.BSONObjectID
import play.modules.reactivemongo.json.BSONFormats._

/**
 * A message class
 *
 * @param _id The BSON object id of the message
 * @param message The message
 */
case class Message(_id: BSONObjectID, message: String)

object Message {
  /**
   * Format for the message.
   *
   * Used both by JSON library and reactive mongo to serialise/deserialise a message.
   */
  implicit val messageFormat = Json.format[Message]
}

i am using it, and you can use more parameters as long as JSON knows how to format them, or, if you have members that are case classes you created, if the have the same:

package models

import play.api.libs.json.Json
import reactivemongo.bson.BSONObjectID
import play.modules.reactivemongo.json.BSONFormats._

/**
 * A message class
 *
 * @param _id The BSON object id of the message
 * @param message The message
 */

case class Name(fName: String, lName: String, mInitial: String)

object Name {
  implicit val nameFormat = Json.format[Name]
}

case class Message(_id: BSONObjectID, message: String, name: Name)

object Message {
  /**
   * Format for the message.
   *
   * Used both by JSON library and reactive mongo to serialise/deserialise a message.
   */
  implicit val messageFormat = Json.format[Message]
}

i still have not figured a way to do it if you have auxiliary constructors, or if you implement apply(...) in the companion. however, the compiler will alert you to that.

Ehud Kaldor
  • 753
  • 1
  • 7
  • 20
  • This actually doesn't answer the question. You created a **json** formatter instead of a **bson** one. Nevertheless there is a macro to generate bson formatters in reactive-bson 0.9 that does the same. – tmbo Dec 18 '13 at 06:55
  • @ehud: if you have auxilliary constructors of your own apply definition you must create a new instance of the Format[A] class check http://stackoverflow.com/questions/20616677/defaults-for-missing-properties-in-play-2-json-formats/20637205?noredirect=1#comment30922752_20637205 for what it can look like (event though in that answer I reuse the macro to avoid rewriting the full parsing by hand it should give you a hint ) – Jean Dec 18 '13 at 11:14
0

You can check how they did it at this link in Reactivemongo documentation: http://stephane.godbillon.com/2012/10/18/writing-a-simple-app-with-reactivemongo-and-play-framework-pt-1.html

implicit object ArticleBSONReader extends BSONReader[Article] {
def fromBSON(document: BSONDocument) :Article = {
  val doc = document.toTraversable
  Article(
    doc.getAs[BSONObjectID]("_id"),
    doc.getAs[BSONString]("title").get.value,
    doc.getAs[BSONString]("content").get.value,
    doc.getAs[BSONString]("publisher").get.value,
    doc.getAs[BSONDateTime]("creationDate").map(dt => new DateTime(dt.value)),
    doc.getAs[BSONDateTime]("updateDate").map(dt => new DateTime(dt.value)))
  }
}
Ayoub
  • 361
  • 4
  • 15
  • I might be wrong, or confused here, but this seems to recive a BSONDocument, while what I have is basically just a single String that looks like the BSON in question. How do I make the leap from the String to the BSONDocument? – Shany Tooper Dec 18 '13 at 09:01
0

Here a solution I'm using. I hope it helps ->

    def bsonToString(bson: BSONDocument): String = {
        val bsonAsKeyValueList = bson.toMap.toList.map {
          case (key, document: BSONDocument) =>
            (key, bsonToString(document))
          case (key, value: BSONValue) =>
            (key, value.toString)
        }
        val bsonAsKeyValueStrings = bsonAsKeyValueList.map {
          case (key, value) =>
            s"""("${key}" -> ${value})"""
        }
        bsonAsKeyValueStrings.mkString("BSONDocument", ", ", "")
      }

Carlos Saltos
  • 1,385
  • 15
  • 15