我已经看了一眼:Scala type deferring,它看起来很接近我的问题,但不幸的是我无法用答案解决它。
所以,这是代码:
我的GenericModel
abstract class GenericModel[T] {
val _id: Option[BSONObjectID]
def withId(newId: BSONObjectID): T
}
我已实施的模型
case class Push
(_id: Option[BSONObjectID], text: String)
extends GenericModel[Push]
{
override def withId(newId: BSONObjectID) = this.copy(_id = Some(newId))
}
object Push{
implicit val pushFormat = Json.format[Push]
}
我的DAO,使用案例类
trait GenericDao[T <: GenericModel[T]] {
val db: DB
val collectionName: String
/**
* Inserts new object
* @param newobject
* @return Some(stringified bsonID) or None if error
*/
def insert(newobject: T)(implicit tjs: Writes[T]): Future[Option[BSONObjectID]] = {
val bsonId = BSONObjectID.generate
val beaconWithId = newobject.withId(bsonId)
db.collection[JSONCollection](collectionName).insert(beaconWithId).map{ lastError =>
if(lastError.ok)
Some(bsonId)
else
None
}
}
}
我收到了错误
No Json serializer as JsObject found for type T. Try to implement an implicit OWrites or OFormat for this type
这里,插入方法
db.collection[JSONCollection](collectionName).insert(beaconWithId)
就像我之前说的那样,我已经尝试过隐式写作。 感谢您的帮助,我希望我没有错过关于beggining的引用主题的内容。
答案 0 :(得分:0)
想法是添加[T : Writes]
,问题在哪里。
你可以试试这个:
trait GenericDao[T <: GenericModel[T]] {
val db: DB
val collectionName: String
/**
* Inserts new object
* @param newobject
* @return Some(stringified bsonID) or None if error
*/
def insert[T : Writes](newobject: T)(implicit tjs: Writes[T]): Future[Option[BSONObjectID]] = {
val bsonId = BSONObjectID.generate
val beaconWithId = newobject.withId(bsonId)
db.collection[JSONCollection](collectionName).insert(beaconWithId).map{ lastError =>
if(lastError.ok)
Some(bsonId)
else
None
}
}
}
或许这个(或两者):
abstract class GenericModel[T : Writes] {
val _id: Option[BSONObjectID]
def withId(newId: BSONObjectID): T
}
答案 1 :(得分:0)
implicit val pushFormat = Json.format[Push]
Json.format扩展了Format [A] trait,后者又扩展了Writes [A]和Reads [A]。所以错误是对的,编译器找不到OWrites来序列化对象。
解决此错误而不是使用Json.format [推送]扩展OWrites和读取
implicit object Push extends OWrites[Push] {
def writes(push: Push): JsObject = Json.obj(
"_id" -> push.id,
"text" -> push.text
}
implicit object pushReads extends Reads[Push] {
def reads(json: JsValue): JsResult[Push] = json match {
case obj: JsObject => try {
val id = (obj \ "_id").asOpt[String]
val text = (obj \ "text").as[String]
JsSuccess(Push(id, text))
} catch {
case cause: Throwable => JsError(cause.getMessage)
}
case _ => JsError("expected.jsobject")
}
}
在DAO中,将[T]写入OWrites [T]
答案 2 :(得分:0)
我有同样的问题,我必须实现一个方法来告诉Object如何成为一个JsValue:
def toJs[T : Writes](o: T) = Json.toJson(o).as[JsObject]
因此我的MongoRepository的插入部分如下所示:
trait MongoRepository[T <: MongoModel] {
lazy val db: DB = {
import scala.concurrent.ExecutionContext.Implicits.global
import reactivemongo.core.nodeset.Authenticate
import scala.collection.JavaConversions._
val driver = new MongoDriver
val connection = driver.connection(
config.getStringList("mongodb.servers"),
MongoConnectionOptions(),
Seq(Authenticate(
config.getString("mongodb.db"),
config.getString("mongodb.credentials.username"),
config.getString("mongodb.credentials.password")
)
)
)
connection.db(config.getString("mongodb.db"))
}
def collectionName: String
def collection = db(collectionName)
def ensureIndexes: Future[List[Boolean]]
def toJs[T : Writes](o: T) = Json.toJson(o).as[JsObject]
def insert(document: T)(implicit writer: Writes[T]): Future[Either[ServiceException, T]] = {
document._id match {
case None => document._id = Some(BSONObjectID.generate)
case Some(exist) => {}
}
document.created = Some(DateTime.now)
document.updated = Some(DateTime.now)
Logger.debug(s"Inserting document: [collection=$collectionName, data=$document]")
recoverOperation(collection.insert(toJs(document))) {
document
}
}
...
}
希望这会有所帮助:)