我正在尝试为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拥有正确的类型。
答案 0 :(得分: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
成为稳定的标识符,即此处将其设为大写。有关详细信息,请参阅this question和answer。
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")
}
}
}
...
}
答案 1 :(得分:0)
尝试将enumerationClass
声明为:
val enumerationClass: Class[T] = m.runtimeClass.asInstanceOf[Class[T]]
您已经知道Manifest
的runtimeClass属于T
类型,因此我不确定您将其声明为val enumerationClass: Class[_ <: Enum[T]]
的原因。 Enum.valueOf
无法使用通配类型,这就是您看到错误的原因。