Home > Enterprise >  Cannot deserialize both object and list of objects
Cannot deserialize both object and list of objects

Time:11-05

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;    
}
  • Related