Deserialising different types to single field using Jackson Deserialising different types to single field using Jackson json json

Deserialising different types to single field using Jackson


In general, I'd discourage the use of arbitrary types of data points. Having strong types gives plenty of benefits about which I can talk if you want. However, since you only talked about deserialization it might be that you are just reading such a JSON produced by someone else.

The solution is quite simply: use Object field.

public static class MyObject {    @JsonProperty("prop")    String prop;    @JsonProperty("value")    Object value;        // <- object}@Testpublic void testUnknownType() throws JsonProcessingException {    final ObjectMapper objectMapper = new ObjectMapper();    final MyObject object1 = objectMapper.readValue("{\n" +        "  \"prop\": \"myprop\",\n" +        "  \"value\": 15.7\n" +        "}", MyObject.class);    Assert.assertEquals(15.7d, object1.value);    final MyObject object2 = objectMapper.readValue("{\n" +        "  \"prop\": \"myprop1\",\n" +        "  \"value\": {\n" +        "    \"attr1\": \"value1\",\n" +        "    \"attr2\": 12.0\n" +        "  }\n" +        "}", MyObject.class);    Assert.assertTrue(object2.value instanceof Map);}


What you could is something like this:

@JsonDeserialize(using = ExampleDeserializer.class)public class Example{String prod;Object value; /*this field will takes multiple types*/}

and the ExampleDeserializer would be like this:

public class ExampleDeserializer extends StdDeserializer<Example> {    public ExampleDeserializer() {        super(Example.class);    }    public ExampleDeserializer(Class<?> vc) {        super(vc);    }@Override    public Example deserialize(JsonParser p, DeserializationContext ctx) throws IOException {        Example ex = new Example();        ObjectCodec mapper = p.getCodec();        if (mapper == null) mapper = new ObjectMapper();        JsonNode tree = mapper.readTree(p);        JsonNode internalNode;        if (tree.get("prod") != null) {          internalNode = tree.get("prod");          prop = internalNode.get("prod").asText();        }       if (tree.get("value") != null) {          internalNode = tree.get("value");          value = (Double) internalNode.get("value").asDouble() or asText()...;        }}


You'll have a slightly easier time of things if you have your different types as different names, so in JSON it should be:

{  prop: "my_map_prop",  mapvalue: {    "attr1": "value1",    "attr2": 12.0  }}

or

{  prop: "my_string_prop",  stringvalue: "string"}

If you do it like this you then have more tools at your disposal to enforce validity.