简体   繁体   English

带枚举值的Scala序列化异常

[英]Scala serialization exception with Enumeration Value

I'm using the play 2.1 framework for scala and the MongoDB Salat plugin. 我正在使用scala的play 2.1框架和MongoDB Salat插件。

When I update an Enumeration.Value I got an exception: 当我更新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]

Inserting the Enumeration.Value works fine. 插入Enumeration.Value工作正常。 My case class looks like: 我的案例类看起来像:

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)

and my update code: 和我的更新代码:

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))))
    }
}

Any ideas how to get that working? 有任何想法如何工作?

EDIT: 编辑:

workaround: it works if I cast the Enumeration.Value toString, but that's not how it should be... 解决方法:如果我将Enumeration.Value转换为toString,它会起作用,但这不是它应该如何...

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

It is possible to add a BSON encoding for Enumeration. 可以为枚举添加BSON编码。 So, the conversion is done in a transparent manner. 因此,转换以透明的方式完成。

Here is the code 这是代码

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)
  }
}

At the time of writing mongoDB doesn't place nice with scala enums, I use a decorator method as a work around. 在撰写本文时,mongoDB并不适合使用scala枚举,我使用装饰器方法作为解决方法。

Say you have this enum: 说你有这个枚举:

object EmployeeType extends Enumeration {
  type EmployeeType = Value
  val Manager, Worker = Value
}

and this mongodb record: 这个mongodb记录:

import EmployeeType._
case class Employee(
  id: ObjectId = new ObjectId
)

In your mongoDB, store the integer index of the enum instead of the enum itself: 在你的mongoDB中,存储枚举的整数索引而不是枚举本身:

case class Employee(
  id: ObjectId = new ObjectId,
  employeeTypeIndex: Integer = 0
){
  def employeeType = EmployeeType(employeeTypeIndex); /* getter */
  def employeeType_=(v : EmployeeType ) = { employeeTypeIndex= v.id} /* setter */
}

The extra methods implement getters and setters for the employee type enum. 额外的方法为员工类型枚举实现getter和setter。

Salat only does its work when you serialize to and from your model object with the grater, not when you do queries with MongoDB-objects yourself. Salat仅在使用grater与模型对象进行序列化时才会工作,而不是在您自己使用MongoDB对象进行查询时。 The mongo driver api knows nothing about the annotation @EnumAs. mongo驱动程序api对注释@EnumAs一无所知。 (In addition to that even if you could use salat for that, how would it be able to know that you are referring to User.language in a generic key->value MongoDBObject?) (除此之外,即使你可以使用salat,它怎么能知道你在泛型键 - >值MongoDBObject中引用User.language?)

So you have to do like you describe in your workaround. 所以你必须像你在你的解决方法中描述的那样做。 Provide the "value" of the enum yourself when you want to do queries. 当您想要查询时,自己提供枚举的“值”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM