1

I have the current issue that I receive a JSON response where I don't know the name of the key (in my example JSON named UnknownSubCategorieX).

The keys are always different from each other.

Here a JSON example:

{
  "UnknownSubCategorie1": [],
  "UnknownSubCategorie2": [
    {
      "orderNumber": "120466",
      "type": "sell",
      "name": "ProductA"
    },
    {
      "orderNumber": "120467",
      "type": "sell",
      "name": "ProductB"
    }
  ],
  "UnknownSubCategorie3": [
    {
      "orderNumber": "120345",
      "type": "sell",
      "name": "ProductA"
    },
    {
      "orderNumber": "134006",
      "type": "sell",
      "name": "ProductB"
    },
    {
      "orderNumber": "134003",
      "type": "sell",
      "name": "ProductB"
    }
  ],
  ...
}

This function could be applied for the inner part

ObjectMapper mapper = new ObjectMapper();
List<OpenOrderPOJO> openOrderPOJOList = null;
try {
    openOrderPOJOList = mapper.readValue(response, mapper.getTypeFactory().constructCollectionType(List.class, OpenOrderPOJO.class));
} catch (IOException e) {
    e.printStackTrace();
}
if (openOrderPOJOList != null) {
    ...continue
}

inner part:

   {
      "orderNumber": "120345",
      "type": "sell",
      "name": "ProductA"
    },
    {
      "orderNumber": "134006",
      "type": "sell",
      "name": "ProductB"
    },
    {
      "orderNumber": "134003",
      "type": "sell",
      "name": "ProductB"
    }

class

@Data
public class OpenOrderPOJO {

    private String orderNumber;
    private String type;
    private String name;

}

With the suggestion of Mạnh Quyết Nguyễn

@Data
public class POJO {
    private Map<String, List<OpenOrderPOJO>> unknownSubCategories;

    @JsonAnySetter
    public void setMap(String key, List<OpenOrderPOJO> value) {
        if (unknownSubCategories == null) {
            unknownSubCategories = new LinkedHashMap<>();
        }
        unknownSubCategories.put(key, value);
    }
}

and this execution

public static void main(String[] args) {

        ObjectMapper mapper = new ObjectMapper();
        List<POJO> openOrderPOJOList = null;
        try {
            openOrderPOJOList = mapper.readValue(JSONResponse, mapper.getTypeFactory().constructCollectionType(List.class, POJO.class));
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (openOrderPOJOList != null) {
            //continue
        }
    }

I get this exception

com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.util.ArrayList` out of START_OBJECT token
 at [Source: (StringReader); line: 1, column: 1]
    at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
    at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1342)
    at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1138)
    at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1092)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.handleNonArray(CollectionDeserializer.java:332)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:265)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:245)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:27)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4013)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3042)
    at Poloniex.PrivateMethods.Main.main(Main.java:30)

Process finished with exit code 0

Please help me to deserialize the whole JSON response.

It could be for example a map ´HashMap´ where the key isUnknownSubCategorie`

However I tried to implement it, I got an exception and have meanwhile really a headache here.

I am not fixed to JACKSON, if someone can only help with GSON I would join this :)

Anna Klein
  • 1,906
  • 4
  • 27
  • 56
  • 1
    Your json looks wrong, duplicate keys are not allowed. Double check your example json.. – kleash Aug 22 '18 at 17:02
  • *However I tried it, I got an exception*: then post a complete minimal example showing what you tried, and post the complete and exact stack trace of the exception. – JB Nizet Aug 22 '18 at 17:05

2 Answers2

3

Look likes you want to map with your JSON where the key is unspecified (your example of duplicated key might confuse other people here).

To dynamic matching, you can use @JsonAnySetter:

@Data
public class POJO {
    private Map<String, List<OpenOrderPOJO>> unknownSubCategories;

    @JsonAnySetter
    public void setMap(String key, List<OpenOrderPOJO> value) {
        if (unknownSubCategories == null) {
            unknownSubCategories = new LinkedHashMap<>();
        }
        unknownSubCategories.put(key, value);
    }
}

Now you can use it to deserialize with ObjectMapper as usual

Mạnh Quyết Nguyễn
  • 17,677
  • 1
  • 23
  • 51
  • Thank you for this. I tried to apply it but unfortunately get an exception. Could you please have an eye on it? I wonder if I have to supply the function for the inner part somewhere, maybe that is the issue? – Anna Klein Aug 23 '18 at 08:49
  • Did you modify something from my suggested code? One note: remove the `static` modifier – Mạnh Quyết Nguyễn Aug 23 '18 at 08:50
  • Ah, I see. Do you have other type of data in your JSON? It complains that you have an object but want to deserialize as an array. – Mạnh Quyết Nguyễn Aug 23 '18 at 08:52
  • No I have just the provided JSON. Do I have to bring the POJO class and the OpenOrderPOJO (for the inner part) somehow together? – Anna Klein Aug 23 '18 at 09:02
  • With your input, I got [this output](https://imgur.com/PetG4zf) So again, please double check your JSON, or just stripping the detail and post your JSON somewhere, so I can check it – Mạnh Quyết Nguyễn Aug 23 '18 at 09:09
  • Thank you very much for your patient. I figured out with your help that this was the mistake: List openOrderPOJOList = null; try { openOrderPOJOList = mapper.readValue(JSONResponse, mapper.getTypeFactory().constructCollectionType(List.class, POJO.class)); Now it works :) – Anna Klein Aug 23 '18 at 09:46
  • Thanks for this answer. I tried this but did not work perfectly for me. I want to know how to obtain the duplicate key fields and all value from `JSON` using the `@JsonAnySetter` when using the `ObjectMapper.treeToValue` method. It would work perfectly when used with the `ObjectMapper.readValue` but when used with the `treeToValue` then `Jackson` stores only the last value of the duplicate key. It ignores the previous values of the duplicated key. I have my post here: https://stackoverflow.com/questions/67413028/jackson-jsonanysetter-ignores-values-of-duplicate-key-when-used-with-jackson-ob – BATMAN_2008 May 10 '21 at 10:36
0

Just add this in you POJO class and getters and setters for it

@JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
yogesh
  • 11
  • 5