Skip to content

java.lang.IllegalArgumentException: Cannot deserialize value of type java.util.ArrayList<RetInfArryDTO> from Object value (token JsonToken.START_OBJECT`) #630

Closed
@oooooooz

Description

@oooooooz

Search before asking

  • I searched in the issues and found nothing similar.

Describe the bug

I use jackson-dataformat-xml to deserialize XML , but it throws exception :
Exception in thread "main" java.lang.IllegalArgumentException: Cannot deserialize value of type java.util.ArrayList<RetInfArryDTO> from Object value (token JsonToken.START_OBJECT)
at [Source: UNKNOWN; line: -1, column: -1] (through reference chain: AnRspDTO["SysHead"]->SysHeadRspDTO["RetInfArry"])

It look like thak jackson unrecognize this type of XML format data , could not treat the array in XML as real array to deserialize , but I think it is a kind of common XML data which contain array type, isn't it ?

I tried annotation like @JsonDeserialize(contentAs = AddrInfArryDTO.class), @JsonAlias({ "IdInfArry", "IdInfArry.array" }), but it did not work for me !

Q1: Is anyone know how to solve this problem?
Q2: If I must use custom JsonDeserializer to solve , how can I get the elementType below ?could not get it from both jsonParser and deserializationContext, and i don't want to write hard code , give exactly elementType here, because too must DTO to be deserialized , write a general custom JsonDeserializer is very necessary!


 @Override
    public List<T> deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
            throws IOException, JsonProcessingException {
        List<T> list = new ArrayList<>();
        ObjectMapper mapper = (ObjectMapper) jsonParser.getCodec();
        JsonNode node = jsonParser.readValueAsTree();

        Iterator<JsonNode> elements = node.elements();
            while (elements.hasNext()) {
                JsonNode element = elements.next();
                T obj = deserializationContext.readValue(element.traverse(), elementType);
                list.add(obj);
        }

        return list;
    }

Here below is my XML data to be deserialized and its DTO object :

(1)XML data like this :

<?xml version="1.0" encoding="UTF-8"?>
<service>
  <SysHead>
    <SvcCd>1234</SvcCd>
    <ScnCd>1245</ScnCd>
     <RetInfArry type="array">
        <array>
                    <RetCd>0000</RetCd>
                    <RetMsg>succ</RetMsg>
         </array>
      </RetInfArry>`
  <BODY>
    <CrpnScop></CrpnScop>
    <IdInfArry type="array">
        <array>
                        <IdentSeqNo>12345</IdentSeqNo>
                        <IdentTp>22</IdentTp>
        </array>
        <array>
                        <IdentSeqNo>1234</IdentSeqNo>
                        <IdentTp>22</IdentTp>
        </array>
     </IdInfArry>
    <AddrInfArry type="array">
      <array>
                      <CustAddr>1234</CustAddr>
                      <AddrTp>12</AddrTp>
       </array>
      <array>
                      <CustAddr>1234</CustAddr>
                      <AddrTp>12</AddrTp>
       </array>
    </AddrInfArry>
    </BODY>
</service>

(2)Here is my DTO , XML deserialize object :

//@JsonProperty work fine, not need to use @JacksonXmlProperty 

@lombok.Data
public class AnRspDTO {
  @JsonProperty("SysHead")
    private SysHeadRspDTO sysHead;

   @JsonProperty("BODY")
    private RspBodyDTO body;

@lombok.Data
public static class RspBodyDTO {

    @JsonProperty("CrpnScop")
     private String crpnScop = "";

    @JsonProperty("IdInfArry")
     private List<IdInfArryDTO> idInfArry = Collections.emptyList();

     @JsonProperty("AddrInfArry")
     private List<AddrInfArryDTO> addrInfArry = Collections.emptyList();

@lombok.Data
public static class IdInfArryDTO {

    @JsonProperty("IdentSeqNo")
     private String identSeqNo = "";

    @JsonProperty("IdentTp")
     private String identTp = "";

}

@lombok.Data
public static class AddrInfArryDTO {

     @JsonProperty("CustAddr")
      private String custAddr = "";

      @JsonProperty("AddrTp")
       private String addrTp = "";

}

}

@lombok.Data
public class SysHeadRspDTO {
  @JsonProperty("SvcCd")
  private String svcCd

  @JsonProperty("ScnCd")
  private String scnCd

  @JsonProperty("RetInfArry")
   private List<RetInfArryDTO> retInfArry = Collections.emptyList();

@lombok.Data
public static class RetInfArryDTO{

    @JsonProperty("RetCd")
    private String retCd;

    @JsonProperty("RetMsg")
    private String retMsg;
}
}

Version Information

pom dependency , current steady version 2.16.0 could not solve the problem too

<dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-xml</artifactId>
<!--            <version>2.16.0</version>-->
            <version>2.12.3</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.datatype</groupId>
            <artifactId>jackson-datatype-jsr310</artifactId>
<!--            <version>2.16.0</version>-->
            <version>2.12.3</version>
        </dependency>

Reproduction

<-- Any of the following

  1. Brief code sample/snippet: include here in preformatted/code section
  2. Longer example stored somewhere else (diff repo, snippet), add a link
  3. Textual explanation: include here
    -->
public static <T> T decode(String msg, Class<T> entityType) {
ObjectMapper objectMapper = getObjectMapper();
        try {
            return objectMapper.readValue(msg, entityType);
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

   public static <T> T convert(Object src, Class<T> dstType) {
        ObjectMapper objectMapper = getObjectMapper();
        return objectMapper.convertValue(src, dstType);
    }

  public static ObjectMapper getObjectMapper(){
  
    XmlMapper.Builder builder = XmlMapper.builder()
                .disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
                .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
                .configure(ToXmlGenerator.Feature.WRITE_XML_DECLARATION,true)
                .configure(MapperFeature.USE_ANNOTATIONS, enableAnno);

return builder.build();
  
 }

 public static void main(String[] args) {
        String xmldata=getXml()//
        Map map =decode(xmldata,Map.class);
        AnRspDTO dtoObj = convert(map,RspBodyDTO.class);
        Assert.notNull(dtoObj)
    }

Expected behavior

No response

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    to-evaluateIssue that has been received but not yet evaluated

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions