I am having trouble parsing the response from an Adobe Campaign API endpoint into a POJO.
I am grabbing the data from the response:
String json = EntityUtils.toString(response.getEntity());
The data (heavily redacted) data looks like this:
{
"content": [
{
"PKey": "@9v59tLj9c.....",
"age": 36,
"birthDate": "1986-04-30",
"blackList": false,
...
},
{
"PKey": "@9f32tLj5c.....",
"age": 32,
"birthDate": "1999-05-11",
"blackList": false,
...
},
...
]
}
I'm instantiating a Jackson ObjectMapper and configuring it such that the root "content" node is ignored.
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
objectMapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
I have tried many different ways of parsing the data into my Profile POJO, without success. There's always an issue related to it being wrapped in "content" node, or being a list of one, or something. For brevity, the code below is for a single POJO, but I have also tried with List<Profile>
since, as mentioned, the response is always a List of one or more.
// object mapper
Profile profile = objectMapper.readValue(json), Profile.class)
// ERROR: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "content" (class com.example.adobecampaignprototype.Profile), not marked as ignorable (0 known properties: ])
// object reader
ObjectReader objectReader = objectMapper.readerFor(Profile.class).withRootName("content");
Profile profile = objectReader.readValue(json);
// ERROR: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `com.example.adobecampaignprototype.Profile` from Array value (token `JsonToken.START_ARRAY`)
// array node
ArrayNode arrayNode = (ArrayNode) objectMapper.readTree(json).get("content");
// ERROR: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "content" (class com.example.adobecampaignprototype.Profile), not marked as ignorable (0 known properties: ])
// json node
JsonNode jsonNodeRoot = objectMapper.readTree(json);
JsonNode jsonNodeNested = jsonNodeRoot.get("content");
JsonNode jsonNodeActual = jsonNodeNested.get(0) // to get profile at index 0
JsonNode jsonNodeActualValue = jsonNodeActual.get("PKey") // to read single property
I've tried the above in many combinations, but have never been able to successfully parse either a Profile or List. I have read the official docs exhaustively, been through tutorials on Baeldung and elsewhere. I feel like this should be a simple thing and there's probably something obvious that I'm overlooking, but unsure what it is. Would be grateful if someone could point me toward the EASY button.
Probably you are overthinking about it, for example if you take a semplified version of your json input file like below as a starting point:
{
"content": [
{
"PKey": "@9v59tLj9c....."
},
{
"PKey": "@9f32tLj5c....."
}
]
}
You can use part of the code you wrote, so one way to deserialize it is to convert your ArrayNode
array of JsonNode
into a Profile[]
array:
@Data
public class Profile {
@JsonProperty("PKey")
private String pKey;
}
ArrayNode arrayNode = (ArrayNode) mapper.readTree(json).get("content");
Profile[] profiles = mapper.convertValue(arrayNode, Profile[].class);
//ok it prints the array [{"PKey":"@9v59tLj9c....."},{"PKey":"@9f32tLj5c....."}]
System.out.println(mapper.writeValueAsString(profiles));