Skip to content
Advertisement

Deserializing json to pojo where json field has different data types

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

enter image description here

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement