3

我正在尝试为 Json4s 编写一个通用的自定义序列化程序,它可以处理类型为 T <: Enum[T] 的 Java 枚举。为此,我想使用 Enum.valueOf 方法,该方法也采用 T <: Enum[T] 类型的类标记。这是我到目前为止所拥有的:

class EnumSerializer[T <: Enum[T]](implicit m: Manifest[T]) extends Serializer[T] {

  val enumerationClass: Class[_ <: Enum[T]] = m.runtimeClass.asInstanceOf[Class[T]]

  def deserialize(implicit format: Formats) :  PartialFunction[(TypeInfo, JValue), T] = {
    case (t @ TypeInfo(enumerationClass, _), json) => {
      json match {
        case JString(value) => Enum.valueOf(enumerationClass, value.toUpperCase()).asInstanceOf[T]
        case value => throw new MappingException(s"Can't convert $value to $enumerationClass")
      }
    }
  }

  def serialize(implicit format: Formats): PartialFunction[Any, JValue] = {
    case i : Enum[T] => JString(i.name())
  }
}

但我收到以下编译错误:

inferred type arguments [_0] do not conform to method valueOf's type parameter bounds [T <: Enum[T]]
case JString(value) => Enum.valueOf(enumerationClass, value.toUpperCase()).asInstanceOf[T]

我不知道如何让 enumerationClass 具有正确的类型。

4

2 回答 2

3

enumerationClass在您的deserialize方法中隐藏val enumerationClass它外部的定义。您的代码相当于:

case (t @ TypeInfo(a, _), json) => {
  json match {
    case JString(value) => Enum.valueOf(a, value.toUpperCase()).asInstanceOf[T]
    case value => throw new MappingException(s"Can't convert $value to $enumerationClass")
  }
}

这不是您想要的:这将始终匹配,因为您不限制课程。您需要制作enumerationClass一个稳定的标识符,即这里将其设为大写。有关更多信息,请参阅此问题答案

class EnumSerializer[T <: Enum[T]](implicit m: Manifest[T]) extends Serializer[T] {

  val EnumerationClass = m.runtimeClass.asInstanceOf[Class[T]]

  def deserialize(implicit format: Formats) :  PartialFunction[(TypeInfo, JValue), T] = {
    case (t @ TypeInfo(EnumerationClass, _), json) => {
      json match {
        case JString(value) => Enum.valueOf(EnumerationClass, value.toUpperCase()).asInstanceOf[T]
        case value => throw new MappingException(s"Can't convert $value to $enumerationClass")
      }
    }
  }

  ...
}
于 2013-06-24T11:07:54.417 回答
0

尝试声明enumerationClass为:

val enumerationClass: Class[T] = m.runtimeClass.asInstanceOf[Class[T]]

您已经知道 runtimeClass 的Manifest类型是T,所以我不确定您为什么将其声明为val enumerationClass: Class[_ <: Enum[T]]. Enum.valueOf不能使用通配符类型,这就是您看到该错误的原因。

于 2013-06-24T11:05:18.650 回答