带枚举值的Scala序列化异常

pic*_*ter 4 serialization scala mongodb playframework-2.0

我正在使用scala的play 2.1框架和MongoDB Salat插件.

当我更新Enumeration.Value时,我得到一个例外:

java.lang.IllegalArgumentException: can't serialize class scala.Enumeration$Val
    at org.bson.BasicBSONEncoder._putObjectField(BasicBSONEncoder.java:270) ~[mongo-java-driver-2.11.1.jar:na]
    at org.bson.BasicBSONEncoder.putIterable(BasicBSONEncoder.java:295) ~[mongo-java-driver-2.11.1.jar:na]
    at org.bson.BasicBSONEncoder._putObjectField(BasicBSONEncoder.java:234) ~[mongo-java-driver-2.11.1.jar:na]
    at org.bson.BasicBSONEncoder.putObject(BasicBSONEncoder.java:174) ~[mongo-java-driver-2.11.1.jar:na]
    at org.bson.BasicBSONEncoder.putObject(BasicBSONEncoder.java:120) ~[mongo-java-driver-2.11.1.jar:na]
    at com.mongodb.DefaultDBEncoder.writeObject(DefaultDBEncoder.java:27) ~[mongo-java-driver-2.11.1.jar:na]
Run Code Online (Sandbox Code Playgroud)

插入Enumeration.Value工作正常.我的案例类看起来像:

case class User(
    @Key("_id") id: ObjectId = new ObjectId,
    username: String,
    email: String,
    @EnumAs language: Language.Value = Language.DE,
    balance: Double,
    added: Date = new Date)
Run Code Online (Sandbox Code Playgroud)

和我的更新代码:

object UserDAO extends ModelCompanion[User, ObjectId] {

    val dao = new SalatDAO[User, ObjectId](collection = mongoCollection("users")) {}

    def update(): WriteResult = {
        UserDAO.dao.update(q = MongoDBObject("_id" -> new ObjectId(id)), o = MongoDBObject("$set" -> MongoDBObject("language" -> Language.EN))))
    }
}
Run Code Online (Sandbox Code Playgroud)

有任何想法如何工作?

编辑:

解决方法:如果我将Enumeration.Value转换为toString,它会起作用,但这不是应该如何...

UserDAO.dao.update(q = MongoDBObject("_id" -> new ObjectId(id)), o = MongoDBObject("$set" -> MongoDBObject("language" -> Language.EN.toString))))
Run Code Online (Sandbox Code Playgroud)

Yan*_*san 5

可以为枚举添加BSON编码.因此,转换以透明的方式完成.

这是代码

RegisterConversionHelpers()
  custom()
  def custom() {
    val transformer = new Transformer {

      def transform(o: AnyRef): AnyRef = o match {
        case e: Enumeration$Val => e.toString
        case _ => o
      }
    }
    BSON.addEncodingHook(classOf[Enumeration$Val], transformer)
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 但是解码怎么样?我怎么写解码器? (2认同)

joh*_*ren 1

Salat 仅在您使用刨丝器序列化模型对象或从模型对象序列化时才起作用,而不是在您自己使用 MongoDB 对象进行查询时起作用。mongo 驱动程序 api 对注释 @EnumAs 一无所知。(除此之外,即使您可以使用 salat 来实现这一点,它如何知道您在通用键->值 MongoDBObject 中引用 User.language ?)

因此,您必须按照解决方法中描述的方式进行操作。当您想要进行查询时,请自行提供枚举的“值”。