0

So I consume data from a REST endpoint (which I don't have access to) that is badly formatted.

In particular, I receive a json object that actually is a list. What is the best way to deal with this? Can it be done with Jackson?

{
    "list": {
        "element 31012991428": {
            "objId": 31012991428,
            "color": "green"
        },
        "element 31012991444": {
            "objId": 31012991444,
            "color": "orange"
        },
        "element 3101298983": {
            "objId": 3101298983,
            "color": "red"
        },
    }
}

Ideally, I want to be able to parse it as follows:

Response.java

public class GetSucherResponse {
    @JsonProperty("elements") //what goes here?
    private List<Element> elements;
}

Element.java

public class Element {
    @JsonProperty("objId")
    private Long objId;
    @JsonProperty("color")
    private String color;
}
simibac
  • 7,672
  • 3
  • 36
  • 48
  • 3
    I dont see how it is badly formatted, the list is a json object that looks valid to me – DownloadPizza Sep 21 '20 at 12:59
  • I assume you are trying to use automarshalling to get it into a list? That wont work. I have an idea however – DownloadPizza Sep 21 '20 at 13:00
  • It is valid but the "elements" are not inside square brackets which doesn't cause errors when marshalling – simibac Sep 21 '20 at 13:02
  • How do you expect to use the "list" property into your class? As list? As map? – sigur Sep 21 '20 at 13:18
  • I have updated the question with more detail. Should be parsed into a list. – simibac Sep 21 '20 at 13:24
  • @simibac since JSON in your example contains an object named "list", with multiple named fields in it, I don't think it's possible to parse it to your classes. Maybe, some custom event- or xpath-based solution might help, but it will also need some extra coding. – Slava Medvediev Sep 21 '20 at 13:49
  • Try to take a look at https://stackoverflow.com/questions/21063367/jackson-mapping-object-or-list-of-object-depending-on-json-input – sigur Sep 21 '20 at 13:58
  • Take a look on similar question: [How do I unwrap a list of list wrapped items in Jackson?](https://stackoverflow.com/questions/57270327/how-do-i-unwrap-a-list-of-list-wrapped-items-in-jackson/57272840#57272840). You need to implement custom deserialiser. Linked question contains one implementation for set. You can change it to return a `List` and it should work for you. – Michał Ziober Sep 21 '20 at 15:04

1 Answers1

0

Created a rough solution
Response class should look like:

@JsonDeserialize(using = ResponseDeserializer.class)
public class Response {
    private List<Element> elements;
    public Response(List<Element> elements) {
        this.elements = elements;
    }
}

Deserializer:

public class ResponseDeserializer extends StdDeserializer<Response> {

    protected ResponseDeserializer() {
        super(Response.class);
    }

    @Override
    public Response deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
        TreeNode rootNode = jsonParser.getCodec().readTree(jsonParser);
        TreeNode listNode = rootNode.get("list");
        List<Element> elements = new ArrayList<>(listNode.size());
        listNode.fieldNames().forEachRemaining(
                s -> elements.add(parseElement(jsonParser, listNode.get(s)))
        );
        return new Response(elements);
    }

    private Element parseElement(JsonParser jsonParser, TreeNode subNode) {
        Element element = null;
        try {
            element = jsonParser.getCodec().treeToValue(subNode, Element.class);
        } catch (JsonProcessingException e) {
            e.printStackTrace(); //TODO handle it in a better way
        }
        return element;
    }

}
Slava Medvediev
  • 1,431
  • 19
  • 35