XStream XStreamMarshaller CannotResolveClassException java.util.ArrayList
XStream XStreamMarshaller CannotResolveClassException java.util.ArrayList
我必须使用 Spring 批处理读取多个 XML 文件。
我正在使用 XStream,但我很难读取对象的 ArrayList。
错误堆栈:
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.4.3.jar:2.4.3]
Caused by: com.thoughtworks.xstream.converters.ConversionException:
---- Debugging information ----
cause-exception : com.thoughtworks.xstream.mapper.CannotResolveClassException
cause-message : workCompany
class : java.util.ArrayList
required-type : java.util.ArrayList
converter-type : com.thoughtworks.xstream.converters.collections.CollectionConverter
path : /person/works/Work/workCompany
line number : 15
class[1] : com.oualid.xmltojava.model.Works
converter-type[1] : com.thoughtworks.xstream.converters.reflection.ReflectionConverter
class[2] : com.oualid.xmltojava.model.Person
version : 5.3.4
-------------------------------
at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:79) ~[xstream-1.4.9.jar:1.4.9]
我的 POJO :
package com.oualid.xmltojava.model;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import java.util.List;
@XStreamAlias("Person")
public class Person {
@XStreamAlias("personId")
private Integer personId;
@XStreamAlias("firstName")
private String firstName;
@XStreamAlias("lastName")
private String lastName;
@XStreamAlias("email")
private String email;
@XStreamAlias("age")
private Integer age;
@XStreamAlias("contactDetails")
private List<String> contactDetails;
@XStreamAlias("works")
private Works works;
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public Integer getPersonId() {
return personId;
}
public void setPersonId(Integer personId) {
this.personId = personId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public List<String> getContactDetails() {
return contactDetails;
}
public void setContactDetails(List<String> contactDetails) {
this.contactDetails = contactDetails;
}
public Works getWorks() {
return works;
}
public void setWorks(Works works) {
this.works = works;
}
}
package com.oualid.xmltojava.model;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamImplicit;
import java.util.List;
@XStreamAlias("works")
public class Works {
@XStreamImplicit(itemFieldName = "Work")
private List<Work> Work;
public List<Work> getWorks() {
return Work;
}
public void setWorks(List<Work> works) {
this.Work = works;
}
}
package com.oualid.xmltojava.model;
import com.thoughtworks.xstream.annotations.XStreamAlias;
@XStreamAlias("Work")
public class Work {
@XStreamAlias("workCompany")
private String workCompany;
@XStreamAlias("workMission")
private String workMission;
public String getWorkCompany() {
return workCompany;
}
public void setWorkCompany(String workCompany) {
this.workCompany = workCompany;
}
public String getWorkMission() {
return workMission;
}
public void setWorkMission(String workMission) {
this.workMission = workMission;
}
}
我的一个 XML 文件:
<?xml version="1.0" encoding="UTF-8"?>
<persons>
<person>
<personId>1</personId>
<firstName>PETER</firstName>
<lastName>SCHMIDT</lastName>
<email>pschmidt0@aboutads.info</email>
<contactDetails>
<string>contact1</string>
<string>contact2</string>
</contactDetails>
<age>28</age>
<works>
<Work>
<workCompany>ESI</workCompany>
<workMission>Java Developper</workMission>
</Work>
<Work>
<workCompany>ESI</workCompany>
<workMission>JS Developper</workMission>
</Work>
</works>
</person>
</persons>
然后reader
@Bean
public StaxEventItemReader<Person> reader(){
StaxEventItemReader<Person> reader = new StaxEventItemReader<Person>();
//reader.setResource(new ClassPathResource("persons.xml"));
reader.setFragmentRootElementName("person");
Map<String,String> aliasesMap =new HashMap<String,String>();
aliasesMap.put("person", "com.oualid.xmltojava.model.Person");
aliasesMap.put("works", "com.oualid.xmltojava.model.Works");
aliasesMap.put("Work", "com.oualid.xmltojava.model.Work");
XStreamMarshaller marshaller = new XStreamMarshaller();
marshaller.setAliases(aliasesMap);
reader.setUnmarshaller(marshaller);
return reader;
}
有关信息,此 reader 已传递到 multiResourceItemReader
,如果我的 XML 文件中没有 <works></works>
,它也能正常工作
Spring Batch 不直接处理解组,而是将其委托给 spring-oxm 的 org.springframework.oxm.Unmarshaller
。所以这个问题与 Spring Batch 本身无关,而是 XStream.
的映射问题
也就是说,根据您定义集合 Person.works
和 Works.Work
的方式,您需要在编组器定义中添加隐式集合映射,如下所示:
Map<Class<?>, String> implicitCollections = new HashMap<>();
implicitCollections.put(Works.class, "Work");
marshaller.setImplicitCollections(implicitCollections);
编辑: 你可以找到一个完整的例子 here。
我post如果其他人会遇到同样的问题,我会回复:
即使我添加了 @XStreamImplicit(itemFieldName = "Work")
,我也发现编组器不知道这个注释。
所以我有两种可能的解决方案:
1- @Mahmoud Ben Hassine 上面的解决方案。
2- 只需激活自动检测注释即可 true
XStreamMarshaller marshaller = new XStreamMarshaller();
marshaller.setAutodetectAnnotations(true);
当然不要忘记为您的列表添加注释:
@XStreamImplicit(itemFieldName = "Work")
private List<Work> Work;
我更喜欢第二个,因为我有一个非常复杂的 XML 阅读大量对象集合,所以我想注释会很干净。
编码愉快:)
我必须使用 Spring 批处理读取多个 XML 文件。
我正在使用 XStream,但我很难读取对象的 ArrayList。
错误堆栈:
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.4.3.jar:2.4.3]
Caused by: com.thoughtworks.xstream.converters.ConversionException:
---- Debugging information ----
cause-exception : com.thoughtworks.xstream.mapper.CannotResolveClassException
cause-message : workCompany
class : java.util.ArrayList
required-type : java.util.ArrayList
converter-type : com.thoughtworks.xstream.converters.collections.CollectionConverter
path : /person/works/Work/workCompany
line number : 15
class[1] : com.oualid.xmltojava.model.Works
converter-type[1] : com.thoughtworks.xstream.converters.reflection.ReflectionConverter
class[2] : com.oualid.xmltojava.model.Person
version : 5.3.4
-------------------------------
at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:79) ~[xstream-1.4.9.jar:1.4.9]
我的 POJO :
package com.oualid.xmltojava.model;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import java.util.List;
@XStreamAlias("Person")
public class Person {
@XStreamAlias("personId")
private Integer personId;
@XStreamAlias("firstName")
private String firstName;
@XStreamAlias("lastName")
private String lastName;
@XStreamAlias("email")
private String email;
@XStreamAlias("age")
private Integer age;
@XStreamAlias("contactDetails")
private List<String> contactDetails;
@XStreamAlias("works")
private Works works;
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public Integer getPersonId() {
return personId;
}
public void setPersonId(Integer personId) {
this.personId = personId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public List<String> getContactDetails() {
return contactDetails;
}
public void setContactDetails(List<String> contactDetails) {
this.contactDetails = contactDetails;
}
public Works getWorks() {
return works;
}
public void setWorks(Works works) {
this.works = works;
}
}
package com.oualid.xmltojava.model;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamImplicit;
import java.util.List;
@XStreamAlias("works")
public class Works {
@XStreamImplicit(itemFieldName = "Work")
private List<Work> Work;
public List<Work> getWorks() {
return Work;
}
public void setWorks(List<Work> works) {
this.Work = works;
}
}
package com.oualid.xmltojava.model;
import com.thoughtworks.xstream.annotations.XStreamAlias;
@XStreamAlias("Work")
public class Work {
@XStreamAlias("workCompany")
private String workCompany;
@XStreamAlias("workMission")
private String workMission;
public String getWorkCompany() {
return workCompany;
}
public void setWorkCompany(String workCompany) {
this.workCompany = workCompany;
}
public String getWorkMission() {
return workMission;
}
public void setWorkMission(String workMission) {
this.workMission = workMission;
}
}
我的一个 XML 文件:
<?xml version="1.0" encoding="UTF-8"?>
<persons>
<person>
<personId>1</personId>
<firstName>PETER</firstName>
<lastName>SCHMIDT</lastName>
<email>pschmidt0@aboutads.info</email>
<contactDetails>
<string>contact1</string>
<string>contact2</string>
</contactDetails>
<age>28</age>
<works>
<Work>
<workCompany>ESI</workCompany>
<workMission>Java Developper</workMission>
</Work>
<Work>
<workCompany>ESI</workCompany>
<workMission>JS Developper</workMission>
</Work>
</works>
</person>
</persons>
然后reader
@Bean
public StaxEventItemReader<Person> reader(){
StaxEventItemReader<Person> reader = new StaxEventItemReader<Person>();
//reader.setResource(new ClassPathResource("persons.xml"));
reader.setFragmentRootElementName("person");
Map<String,String> aliasesMap =new HashMap<String,String>();
aliasesMap.put("person", "com.oualid.xmltojava.model.Person");
aliasesMap.put("works", "com.oualid.xmltojava.model.Works");
aliasesMap.put("Work", "com.oualid.xmltojava.model.Work");
XStreamMarshaller marshaller = new XStreamMarshaller();
marshaller.setAliases(aliasesMap);
reader.setUnmarshaller(marshaller);
return reader;
}
有关信息,此 reader 已传递到 multiResourceItemReader
,如果我的 XML 文件中没有 <works></works>
,它也能正常工作
Spring Batch 不直接处理解组,而是将其委托给 spring-oxm 的 org.springframework.oxm.Unmarshaller
。所以这个问题与 Spring Batch 本身无关,而是 XStream.
也就是说,根据您定义集合 Person.works
和 Works.Work
的方式,您需要在编组器定义中添加隐式集合映射,如下所示:
Map<Class<?>, String> implicitCollections = new HashMap<>();
implicitCollections.put(Works.class, "Work");
marshaller.setImplicitCollections(implicitCollections);
编辑: 你可以找到一个完整的例子 here。
我post如果其他人会遇到同样的问题,我会回复:
即使我添加了 @XStreamImplicit(itemFieldName = "Work")
,我也发现编组器不知道这个注释。
所以我有两种可能的解决方案:
1- @Mahmoud Ben Hassine 上面的解决方案。
2- 只需激活自动检测注释即可 true
XStreamMarshaller marshaller = new XStreamMarshaller();
marshaller.setAutodetectAnnotations(true);
当然不要忘记为您的列表添加注释:
@XStreamImplicit(itemFieldName = "Work")
private List<Work> Work;
我更喜欢第二个,因为我有一个非常复杂的 XML 阅读大量对象集合,所以我想注释会很干净。
编码愉快:)