如何编写自定义Jackson反序列化器以将包含原始json的json对象反序列化为单个对象?

时间:2017-01-11 05:59:11

标签: java json scala jackson deserialization

使用Jackson(> 2.0)库,我想将来自后端的数据反序列化,这些数据我无法控制到包含包装器ID的单个对象以及包含该数据的所有数据中。包装器中包含的原始JSON字符串。如何在不定义包装类的情况下编写自定义Jackson反序列化器来创建Movie的新对象?

数据:

{
  "id": "1",
  "rawMovieData": "{\"name\": \"Office Space\", \"director\": \"Mike Judge\"}"
}

数据模型:

case class Movie(id: String, name: String, director: String)

我当前的反序列化器看起来像这样:

class MovieDeserializer extends JsonDeserializer[Movie] {
    override def deserialize(jp: JsonParser, ctxt: DeserializationContext): Movie {
        val wrapper: JsonNode = jp.getCodec.readValue(jp)
        val id: String = wrapper.get("id").asInstanceOf[TextNode].textValue
        val rawMovie: String = wrapper.get("rawMovieData").asInstanceOf[TextNode].textValue
        //How do I now deserialize rawMovie?

        Movie(id, name, director)
    }
}

注意:我的问题被定义为Scala,但我认为Java方法足够相似而不重要。所以Java中的答案是可以接受的。

2 个答案:

答案 0 :(得分:1)

使用JAXB。它代表 for Java API for XML Binding and is 位于javax.xml.bind中 封装

您将需要Eclipse MOXy提供程序作为依赖项。如果您正在进行Java EE编程,那么它已经存在。

以下是实施:

@XmlRootElement
@XmlAccessorType(FIELD)
public class Movie {

    @XmlElement
    private int id;

    @XmlElement
    private String rawMovieData;

    public Movie() {
        // must have a default constructor if you define a non-default
    }

}

接下来,看看here如何实际进行解组。

答案 1 :(得分:0)

我找到了答案!必须创建另一个解析器来解析原始json。

class MovieDeserializer extends JsonDeserializer[Movie] {
    override def deserialize(jp: JsonParser, ctxt: DeserializationContext): Movie {
        val wrapper: JsonNode = jp.getCodec.readValue(jp)
        val id: String = wrapper.get("id").asInstanceOf[TextNode].textValue
        val rawMovie: String = wrapper.get("rawMovieData").textValue

        //Create a new parser to parse the raw json string
        val rawMovieParser: JsonParser = jp.getCodec.getFactory.createParser(rawMovie)
        val movieNode: JsonNode = rawMovieParser.getCodec.readValue(rawMovieParser)
        val name: String = movieNode.get("name").textValue
        val director: String = movieNode.get("director").textValue

        Movie(id, name, director)
    }
}