I'm trying to deserialize a response of either an Object or a List of Objects from our southbound API. Now, I tried just parsing an object or a List of Objects with this code just removing either of the two and it works. So I'm sure either of the parsing I have below works, but when I am trying to combine both parsers into one, I get an error of
Cannot deserialize instance of object out of START_ARRAY token
This is even though the payload with object is correctly formatted and this code below could convert a single object to a List of Object and vice versa.
Below is the code that I have.
@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonNaming(PropertyNamingStrategy.UpperCamelCaseStrategy.class)
// @JsonInclude(JsonInclude.Include.NON_NULL)
public final class GetCreditCardInfo {
// Deserializer for List of Objects
@JsonAlias("ns:return")
private List<CreditCardDetails> details;
// Deserializer for an Object
@JsonAlias("ns:return")
private CreditCardDetails detailsObject;
public List<CreditCardDetails> getDetails() {
// List< CreditCardDetails > list = List.of( detailsObject ) ;
if(details == null) {
details = List.of(detailsObject);
} else {
}
return details;
}
}
What the code does above is that i tries to parse either an object or a list of object. If it cant get a list of object, it would then try to parse the object into a list of object, otherwise, it would retain the list of object it got from the southbound API.
What do I do to make this work as I intended?. Thanks
Sample JSON List of Objects
{
"soapenv:Envelope":{
"soapenv:Body":{
"ns:getCreditCardResponse":{
"xmlns:ns":"",
"ns:return":[
{
"ax21:cif":"1"
},
{
"ax21:cif":"2"
}
],
"xmlns:ax21":"",
"xmlns:ax23":""
}
},
"xmlns:soapenv":"http://schemas.xmlsoap.org/soap/envelope/"
}
}
Sample JSON Object:
{
"soapenv:Envelope":{
"soapenv:Body":{
"ns:getCreditCardResponse":{
"xmlns:ns":"",
"ns:return":{
"ax21:cif":"1"
},
"xmlns:cif":""
}
},
"xmlns:soapenv":"http://schemas.xmlsoap.org/soap/envelope/"
}
}
PS:
- The Sample JSON Objects could already be deserialized by the two deserializers that I have in the code
- I also tried annotating my class with
@JsonInclude(JsonInclude.Include.NON_NULL)
to ignore deserialization errors with non existent json field, but still the issue persist.
Sample: Object Deserializer
@JsonIgnoreProperties(ignoreUnknown = true)
@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonNaming(PropertyNamingStrategy.UpperCamelCaseStrategy.class)
public final class CreditCardDetails {
@JsonAlias("ax21:cif")
private String cif;
}
CodePudding user response:
You can just add the @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
over your private List<CreditCardDetails> details;
in GetCreditCardInfo
class.
This way if there is only one value (ns:return
is an object) in the json, it will be deserialized as one-element List in java.
So try changing GetCreditCardInfo
to the following:
@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonNaming(PropertyNamingStrategy.UpperCamelCaseStrategy.class)
// @JsonInclude(JsonInclude.Include.NON_NULL)
public final class GetCreditCardInfo {
@JsonAlias("ns:return")
@JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
private List<CreditCardDetails> details;
}