I’m trying to deserialize json to java pojo and I can’t wrap my head around how should I begin to create a java object that could be used to deserialize json like this:
{ "links": [], "version": 2, "executionState": "completed", "outputs": [ { "name": "identifier", "value": "2411" }, { "name": "segment", "value": "COMPLEX" }, { "name": "rules", "value": [ { "metadata": [ { "ID": "int" }, { "NAME": "string" }, ] }, { "data": [ [ 2, "S1" ], [ 21, "S6" ] ] } ] } ] }
I’m working with jackson and looking to use something like this: MyPojo response = mapper.readValue(jsonString, MyPojo.class)
The biggest struggle is those “value” elements, where some fields contain simple String and in other cases have an array of elements
I’ve tried to create an abstract class for the element “value”, and then 2 more classes that would extend abstract class. But that didn’t work
Advertisement
Answer
The best way is create a custom type resolver:
static class Outputs { public String name; @JsonDeserialize(using = OutputsDeserializer.class) public OutputsValue value; } static abstract class OutputsValue { } @AllArgsConstructor static class Outputs1 extends OutputsValue { public String value; } @AllArgsConstructor static class Outputs2 extends OutputsValue { public List<Outputs2Item> value; } static class OutputsDeserializer extends JsonDeserializer<OutputsValue> { @Override public OutputsValue deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { ObjectCodec codec = jp.getCodec(); JsonNode node = codec.readTree(jp); if (node.getNodeType().toString().equalsIgnoreCase("STRING")) return new Outputs1(codec.treeToValue(node, String.class)); List<Outputs2Item> xs = new ArrayList<>(); node.elements().forEachRemaining(e -> { try { xs.add(codec.treeToValue(e, Outputs2Item.class)); } catch (JsonProcessingException ex) { ex.printStackTrace(); } }); return new Outputs2(xs); } } static class Outputs2Item { public List<Outputs2ItemMeta> metadata; public List<Object /* integer | string */ > data; } static class Outputs2ItemMeta { public String ID; public String NAME; } static class Pojo { public List<String> links; public int version; public String executionState; public List<Outputs> outputs; }
running with
final Pojo o = new ObjectMapper().readValue(new File("/home/josejuan/tmp/z.json"), Pojo.class);
the object contains all required values