0

Using the Jackson (>2.0) library, I would like to deserialize data that is coming from a backend that I do not control into a single object that contains the id of the wrapper as well as all of the data within the raw JSON string that is contained in the wrapper. How would I write a custom Jackson deserializer to create a new object of Movie without defining a wrapper class?

The data:

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

The data model:

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

My current deserializer looks like this:

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)
    }
}

Note: My question is defined as Scala, but I think a Java approach would be similar enough as to not matter. So an answer in Java would be acceptable.

Segfault
  • 53
  • 5

2 Answers2

1

Use JAXB. It stands for Java API for XML Binding and is located in javax.xml.bind package.

You will need the Eclipse MOXy provider as dependency. If you're doing Java EE programming, it is already there for you.

Here's the implementation:

@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
    }

}

Next, take a look here how to actually do the unmarshalling.

Community
  • 1
  • 1
Mordechai
  • 15,437
  • 2
  • 41
  • 82
  • Can you really use JAXB to unmarshal `JSON`? – OldCurmudgeon Jan 11 '17 at 06:47
  • [Yes](http://stackoverflow.com/questions/13134563/json-string-to-object-mapping), I do that all day. You'll need Eclipse MOXy jaxb provider. – Mordechai Jan 11 '17 at 14:23
  • While this might be a good solution for somebody looking for a general approach to (un)marshalling JSON. This doesn't address the nature of my question which is specific to the Jackson library. I've made that more clear in the body of the question. – Segfault Jan 11 '17 at 16:48
0

I found the answer! Another parser must be created to parse the raw 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)
    }
}
Segfault
  • 53
  • 5