Jackson scala 模块:反序列化案例对象枚举
Jackson scala module: deserialize case object enumeration
我正在使用 Jackson scala 模块,我需要 serialize/deserialize case 对象枚举。序列化工作正常,但是当反序列化回值时,我得到一个 com.fasterxml.jackson.databind.exc.InvalidDefinitionException
。有办法让它工作吗?我想避免使用 "classic" scala 枚举,因为我会失去定义枚举层次结构的能力。
用于测试的代码:
import com.fasterxml.jackson.annotation.JsonValue
import com.fasterxml.jackson.databind.{DeserializationFeature, ObjectMapper}
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import com.fasterxml.jackson.module.scala.experimental.ScalaObjectMapper
sealed trait Operations { @JsonValue def jsonValue: String }
case object Foo extends Operations { override def jsonValue: String = "Foo" }
case object Bar extends Operations { override def jsonValue: String = "Bar" }
sealed trait RichOperations extends Operations
case object Baz extends RichOperations { override def jsonValue: String = "Baz" }
object JsonUtils extends App {
val jsonMapper = new ObjectMapper() with ScalaObjectMapper
jsonMapper.registerModule(DefaultScalaModule)
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
def toJson(value: Any): String = jsonMapper.writeValueAsString(value)
def fromJson[T: Manifest](json: String): T = jsonMapper.readValue[T](json)
println(toJson(Foo)) // "Foo"
println(toJson(Bar)) // "Bar"
println(toJson(Baz)) // "Baz"
println(fromJson[Operations](toJson(Foo))) // throws InvalidDefinitionException
println(fromJson[Operations](toJson(Bar)))
println(fromJson[RichOperations](toJson(Baz)))
}
我解决了定义自定义反序列化器的问题。
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.{DeserializationContext, JsonDeserializer}
class OperationsDeserializer extends JsonDeserializer[Operations] {
override def deserialize(p: JsonParser, ctxt: DeserializationContext): Operations = {
p.getValueAsString match {
case Foo.jsonValue => Foo
case Bar.jsonValue => Bar
case value => throw new IllegalArgumentException(s"Undefined deserializer for value: $value")
}
}
}
class RichOperationsDeserializer extends JsonDeserializer[Operations] {
override def deserialize(p: JsonParser, ctxt: DeserializationContext): Operations = {
p.getValueAsString match {
case Foo.jsonValue => Foo
case Bar.jsonValue => Bar
case Baz.jsonValue => Baz
case value => throw new IllegalArgumentException(s"Undefined deserializer for value: $value")
}
}
}
此外,由于 match/case 中需要稳定的标识符,我将 jsonValue
从 def
更改为 val
:不幸的是,这需要声明 @JsonValue
每个案例对象枚举中的注释。
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
@JsonDeserialize(using = classOf[OperationsDeserializer])
sealed trait Operations { val jsonValue: String }
case object Foo extends Operations { @JsonValue override val jsonValue: String = "Foo" }
case object Bar extends Operations { @JsonValue override val jsonValue: String = "Bar" }
@JsonDeserialize(using = classOf[RichOperationsDeserializer])
sealed trait RichOperations extends Operations
case object Baz extends RichOperations { @JsonValue override val jsonValue: String = "Baz" }
我正在使用 Jackson scala 模块,我需要 serialize/deserialize case 对象枚举。序列化工作正常,但是当反序列化回值时,我得到一个 com.fasterxml.jackson.databind.exc.InvalidDefinitionException
。有办法让它工作吗?我想避免使用 "classic" scala 枚举,因为我会失去定义枚举层次结构的能力。
用于测试的代码:
import com.fasterxml.jackson.annotation.JsonValue
import com.fasterxml.jackson.databind.{DeserializationFeature, ObjectMapper}
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import com.fasterxml.jackson.module.scala.experimental.ScalaObjectMapper
sealed trait Operations { @JsonValue def jsonValue: String }
case object Foo extends Operations { override def jsonValue: String = "Foo" }
case object Bar extends Operations { override def jsonValue: String = "Bar" }
sealed trait RichOperations extends Operations
case object Baz extends RichOperations { override def jsonValue: String = "Baz" }
object JsonUtils extends App {
val jsonMapper = new ObjectMapper() with ScalaObjectMapper
jsonMapper.registerModule(DefaultScalaModule)
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
def toJson(value: Any): String = jsonMapper.writeValueAsString(value)
def fromJson[T: Manifest](json: String): T = jsonMapper.readValue[T](json)
println(toJson(Foo)) // "Foo"
println(toJson(Bar)) // "Bar"
println(toJson(Baz)) // "Baz"
println(fromJson[Operations](toJson(Foo))) // throws InvalidDefinitionException
println(fromJson[Operations](toJson(Bar)))
println(fromJson[RichOperations](toJson(Baz)))
}
我解决了定义自定义反序列化器的问题。
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.{DeserializationContext, JsonDeserializer}
class OperationsDeserializer extends JsonDeserializer[Operations] {
override def deserialize(p: JsonParser, ctxt: DeserializationContext): Operations = {
p.getValueAsString match {
case Foo.jsonValue => Foo
case Bar.jsonValue => Bar
case value => throw new IllegalArgumentException(s"Undefined deserializer for value: $value")
}
}
}
class RichOperationsDeserializer extends JsonDeserializer[Operations] {
override def deserialize(p: JsonParser, ctxt: DeserializationContext): Operations = {
p.getValueAsString match {
case Foo.jsonValue => Foo
case Bar.jsonValue => Bar
case Baz.jsonValue => Baz
case value => throw new IllegalArgumentException(s"Undefined deserializer for value: $value")
}
}
}
此外,由于 match/case 中需要稳定的标识符,我将 jsonValue
从 def
更改为 val
:不幸的是,这需要声明 @JsonValue
每个案例对象枚举中的注释。
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
@JsonDeserialize(using = classOf[OperationsDeserializer])
sealed trait Operations { val jsonValue: String }
case object Foo extends Operations { @JsonValue override val jsonValue: String = "Foo" }
case object Bar extends Operations { @JsonValue override val jsonValue: String = "Bar" }
@JsonDeserialize(using = classOf[RichOperationsDeserializer])
sealed trait RichOperations extends Operations
case object Baz extends RichOperations { @JsonValue override val jsonValue: String = "Baz" }