user82928 user82928 - 1 month ago 15
JSON Question

How do I configure Jackson ObjectMapper to deserialize all fields of type Foo into instances of SubclassOfFoo?

I'm deserializing a large json value. Deeply nested within that value is a json object like the following:

{
"fieldOne": "valueOne",
"fieldTwo": {
"innerField": "innerValue"
}
}


I'm using the Jackson
ObjectMapper
to deserialize the large json value into a 3rd party class. Deeply nested within that 3rd party class is another 3rd party class:

public class DeepThirdPartyClass {
public String fieldOne;
}


which unfortunately is missing the
fieldTwo
property. I can create my own class which adds the missing field:

public class MyClass extends DeepThirdPartyClass {
public MySubObject fieldTwo;
}


How do I configure jackson so that whenever it attempts to deserialize a value to
DeepThirdPartyClass
, it deserializes to
MyClass
instead?

Answer

I reworked @olga-khylkouskaya's solution to fit my problem:

@Test
public void newDeserializer() throws Exception {
    ObjectMapper objectMapper = new ObjectMapper();
    SimpleModule module = new SimpleModule("DeepThirdPartyClass subclass override", new Version(1, 0, 0, "FINAL", "com.example", "deep-third-party-class-override"));
    module.addDeserializer(DeepThirdPartyClass.class, new JsonDeserializer<DeepThirdPartyClass>() {
        @Override
        public DeepThirdPartyClass deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
            return p.readValueAs(MyClass.class);
        }
    });
    objectMapper.registerModule(module);
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

    String json = "{\n" +
            "  \"middle\": {\n" +
            "    \"fieldOne\": \"valueOne\",\n" +
            "    \"fieldTwo\": {\n" +
            "      \"fieldThree\": \"valueThree\"\n" +
            "    }\n" +
            "  }\n" +
            "}\n";

    ThirdPartyClass thirdPartyClass = objectMapper.readValue(json, ThirdPartyClass.class);
}

public class ThirdPartyClass {
    public DeepThirdPartyClass middle;
}

public class InnerClass {
    public String fieldThree;
}