简体   繁体   English

将Enumeration字段序列化为BSON的异常

[英]Exception serializing Enumeration field to BSON

I am using PlayFramework 2.6 with SCALA and mongodb-driver. 我正在使用带有SCALA和mongodb-driver的PlayFramework 2.6。

Struggling with Eumeration serialization on write. 在写时遇到枚举序列化的问题。

When I try to insert object containing enum fields I get exception: 当我尝试插入包含枚举字段的对象时,出现异常:

Caused by: org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class scala.Enumeration$Val.
at org.bson.codecs.configuration.CodecCache.getOrThrow(CodecCache.java:46)
at org.bson.codecs.configuration.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:63)
at org.bson.codecs.configuration.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:37)
at org.mongodb.scala.bson.codecs.macrocodecs.MacroCodec.writeValue(MacroCodec.scala:167)
at org.mongodb.scala.bson.codecs.macrocodecs.MacroCodec.writeValue$(MacroCodec.scala:162)

I created codecs for object itself, also tried to create codec for enumeration class type, but looks like it correct way. 我为对象本身创建了编解码器,还尝试为枚举类类型创建编解码器,但是看起来它是正确的方式。

  val routeTypeCodec: CodecProvider = Macros.createCodecProvider[RouteTypeClass]
  val routeCodec: CodecProvider = Macros.createCodecProviderIgnoreNone[Route]

enumeration: 列举:

class RouteTypeClass extends TypeReference[RouteType.type]

object RouteType extends Enumeration {
  type RouteType = Value
  val Repeat, OneTime = Value
}

object for save: 保存对象:

case class Route(
 ...
 routeType: RouteType
 ...
);

How to write codec for enum fields, except defining this fields as a String. 如何为枚举字段编写编解码器,但将此字段定义为String除外。

Drop the use of enums. 删除枚举的使用。 Instead, use sealed trait and case classes. 而是使用密封的特征和案例类。 Not too elegant solution, but works. 不太优雅的解决方案,但可行。

sealed trait RouteType {
  def routeType: String
}

case class Repeat() extends RouteType {
  override val routeType: String = "Repeat"
}
case class OneTime() extends RouteType {
  override val routeType: String = "OneTime"
}

objet RouteType {
  def parseFromString(value: String): Option[RouteType] = {
    Vector(Repeat(), OneTime().find(_.routeType == value)
  }
}

and write a custom BSON codec for these 并为此编写自定义BSON编解码器

import org.bson.{BsonReader, BsonWriter}
import org.bson.codecs.{Codec, DecoderContext, EncoderContext}

class RouteTypeCodec extends Codec[RouteType] {
  override def encode(
    writer: BsonWriter,
    value: RouteType,
    encoderContext: EncoderContext
  ): Unit = writer.writeString(value.routeType)
  override def getEncoderClass: Class[RouteType] = classOf[RouteType]
  override def decode(reader: BsonReader,
                        decoderContext: DecoderContext): RouteType= {
    val value = reader.readString()
    val result = RouteType.parseFromString(value)
    if (result.isDefined) result.get else throw new IllegalArgumentException("No such RouteType")
  }
}

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

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