3
votes

I'm trying to write readers/writers for my case classes after reading:

but I'm having trouble in making it work.

I have a leadCategory that can consist of several word objects.

package models

import org.joda.time.DateTime
import reactivemongo.bson._
import reactivemongo.bson.handlers.{BSONWriter, BSONReader}
import reactivemongo.bson.BSONDateTime
import reactivemongo.bson.BSONString

LeadCategory:

case class LeadCategory(
                         id: Option[BSONObjectID],
                         categoryId: Long,
                         categoryName: String,
                         creationDate: Option[DateTime],
                         updateDate: Option[DateTime],
                         words: List[Word]
                         )

object LeadCategory {

  implicit object LeadCategoryBSONReader extends BSONReader[LeadCategory] {
    def fromBSON(document: BSONDocument): LeadCategory = {
      val doc = document.toTraversable
      LeadCategory(
        doc.getAs[BSONObjectID]("_id"),
        doc.getAs[BSONLong]("caregoryId").get.value,
        doc.getAs[BSONString]("categoryName").get.value,
        doc.getAs[BSONDateTime]("creationDate").map(dt => new DateTime(dt.value)),
        doc.getAs[BSONDateTime]("updateDate").map(dt => new DateTime(dt.value)),
        doc.getAs[List[Word]]("words").toList.flatten)
    }
  }

  implicit object LeadCategoryBSONWriter extends BSONWriter[LeadCategory] {
    def toBSON(leadCategory: LeadCategory) = {
      BSONDocument(
        "_id" -> leadCategory.id.getOrElse(BSONObjectID.generate),
        "caregoryId" -> BSONLong(leadCategory.categoryId),
        "categoryName" -> BSONString(leadCategory.categoryName),
        "creationDate" -> leadCategory.creationDate.map(date => BSONDateTime(date.getMillis)),
        "updateDate" -> leadCategory.updateDate.map(date => BSONDateTime(date.getMillis)),
        "words" -> leadCategory.words)
    }
  }

Word:

case class Word(id: Option[BSONObjectID], word: String)

object Word {

  implicit object WordBSONReader extends BSONReader[Word] {
    def fromBSON(document: BSONDocument): Word = {
      val doc = document.toTraversable
      Word(
        doc.getAs[BSONObjectID]("_id"),
        doc.getAs[BSONString]("word").get.value
      )
    }
  }

  implicit object WordBSONWriter extends BSONWriter[Word] {
    def toBSON(word: Word) = {
      BSONDocument(
        "_id" -> word.id.getOrElse(BSONObjectID.generate),
        "word" -> BSONString(word.word)
      )
    }

  }    
}

I'm getting a compile error at:

"words" -> leadCategory.words)

stating:

Too many arguments for method apply(ChannelBuffer)
Type mismatch found: (String, List[Words]) required required implicits.Producer[(String, BsonValue)]

What have I missed? Maybe I have misunderstood the docs...

2
Thank you for your tip, but I'm not sure I understand. So instead of "words" -> leadCategory.words I should wrap this in a BsonValue? Could you give me an example?jakob

2 Answers

0
votes

Try to declare the "Word" implicit objects above the "LeadCategory", if you are putting all of it in the same file.

Scala cannot find the implicit objects for the List[Word] - assuming you are using ReactiveMongo 0.9.

0
votes

All of your types should a derivative of a BSON type. I think you want to use BSONArray instead of a List.