Description
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
- Brief code sample/snippet: include here in preformatted/code section
- Longer example stored somewhere else (diff repo, snippet), add a link
- 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