反序列化Scala case类时,如何跳过Jackson中的包装JSON对象?

反序列化Scala case类时,如何跳过Jackson中的包装JSON对象?,json,scala,jackson,Json,Scala,Jackson,我有来自外部系统的以下格式的数据: { "type": "text", "data": { "text": "Here's some text" } } type有许多值,在data中有不同的字段,所有值都有相应的case类,它们应该作为顶级结构的一部分反序列化到这些case类中,例如: case class TopLevel(parts: Part) sealed trait Part case class Text(text: String) extends Part

我有来自外部系统的以下格式的数据:

{
  "type": "text",
  "data": {
    "text": "Here's some text"
  }
}
type
有许多值,在
data
中有不同的字段,所有值都有相应的case类,它们应该作为顶级结构的一部分反序列化到这些case类中,例如:

case class TopLevel(parts: Part)
sealed trait Part
case class Text(text: String) extends Part
case class Image(url: String, ...) extends Part
...

如果不在
Part
周围创建包装器,如何以一种好的方式完成这项工作?

您需要为您的类型创建一个自定义序列化程序。大概是这样的:

import org.json4s.{CustomSerializer, DefaultFormats, Extraction, JObject, JString}
import org.json4s.jackson.JsonMethods.parse
import org.json4s.jackson.Serialization

class PartSerializer extends CustomSerializer[Part](format => ( {
  case JObject(("type", JString(typeString)) :: ("data", obj) :: Nil) =>
    implicit val f = format

    typeString match {
      case "text" =>
        Extraction.extract[Text](obj)
      case "image" =>
        Extraction.extract[Image](obj)
    }
}, {
  case text: Text =>
    implicit val f = format

    JObject(List(
      ("type", JString("text")),
      ("data", JObject(List(
        ("text", JString(text.text))))
      ),
    ))
  case img: Image =>
    implicit val f = format

    JObject(List(
      ("type", JString("image")),
      ("data", JObject(List(
        ("url", JString(img.url))))
      ),
    ))
}
))
implicit val formats = DefaultFormats + new PartSerializer()

// Parse JSON
val part = Extraction.extract[Part](parse(json))
// Generate JSON
val json = Serialization.write(part)
然后您可以这样使用它:

import org.json4s.{CustomSerializer, DefaultFormats, Extraction, JObject, JString}
import org.json4s.jackson.JsonMethods.parse
import org.json4s.jackson.Serialization

class PartSerializer extends CustomSerializer[Part](format => ( {
  case JObject(("type", JString(typeString)) :: ("data", obj) :: Nil) =>
    implicit val f = format

    typeString match {
      case "text" =>
        Extraction.extract[Text](obj)
      case "image" =>
        Extraction.extract[Image](obj)
    }
}, {
  case text: Text =>
    implicit val f = format

    JObject(List(
      ("type", JString("text")),
      ("data", JObject(List(
        ("text", JString(text.text))))
      ),
    ))
  case img: Image =>
    implicit val f = format

    JObject(List(
      ("type", JString("image")),
      ("data", JObject(List(
        ("url", JString(img.url))))
      ),
    ))
}
))
implicit val formats = DefaultFormats + new PartSerializer()

// Parse JSON
val part = Extraction.extract[Part](parse(json))
// Generate JSON
val json = Serialization.write(part)

如果
零件
数据嵌入到外部对象中,此功能也会起作用。

谢谢!我如何将其用于
对象映射器
?看起来您似乎调用了
mapper.addSerializer(Part.class,new PartSerializer())
,但我没有使用对象映射器,因此这可能是错误的。哦,等等。我一定很累了。我的意思是反序列化,而不是序列化:/A
CustomSerializer
同时执行序列化和反序列化,如我的示例所示。那么,
addSerializer
是否仍能正常工作?正如我所说,我不使用对象映射器,所以我无法轻松测试。你能在
部分添加注释吗?
?是的,模型的内部表示是我的