【问题标题】:XStream XStreamMarshaller CannotResolveClassException java.util.ArrayListXStream XStreamMarshaller CannotResolveClassException java.util.ArrayList
【发布时间】:2021-03-15 21:42:51
【问题描述】:

我必须使用 Spring Batch 读取多个 XML 文件。

我正在使用 XStream,但我正在努力读取 ArrayList Of objects。

错误堆栈:

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>

那个读者

@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;
    }

有关信息,此阅读器已传递到 multiResourceItemReader,如果我的 XML 文件中没有 &lt;works&gt;&lt;/works&gt;,它就可以正常工作

【问题讨论】:

    标签: java spring spring-boot spring-batch xstream


    【解决方案1】:

    Spring Batch 不直接处理解组,它将其委托给 spring-oxm 的 org.springframework.oxm.Unmarshaller。所以这个问题与 Spring Batch 本身无关,而是 XStream 的映射问题。

    也就是说,根据您定义集合 Person.worksWorks.Work 的方式,您需要在编组器定义中添加如下隐式集合映射:

    Map<Class<?>, String> implicitCollections = new HashMap<>();
    implicitCollections.put(Works.class, "Work");
    marshaller.setImplicitCollections(implicitCollections);
    

    编辑:你可以找到一个完整的例子here

    【讨论】:

    • 感谢 Mahmoud 的回复,它有效,但我有更干净的解决方案,只需将 AutoDetectAnnotations 设置为 true,以避免添加隐式集合,因为原始 XML 确实比我发布的更复杂。
    【解决方案2】:

    如果其他人会遇到同样的问题,我会发布回复:

    即使我添加了@XStreamImplicit(itemFieldName = "Work"),我发现编组器并不知道这个注释。

    所以对我来说有两种可能的解决方案:

    1- 以上@Mahmoud Ben Hassine 解决方案。

    2- 只需激活true的自动检测注释

    XStreamMarshaller marshaller = new XStreamMarshaller();
    marshaller.setAutodetectAnnotations(true);
    

    当然不要忘记为您的列表添加注释:

    @XStreamImplicit(itemFieldName = "Work")
    private List<Work> Work;
    

    我更喜欢第二个,因为我有一个非常复杂的 XML 可以读取很多对象集合,所以我猜注释会很干净。

    编码愉快:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-02
      • 1970-01-01
      • 1970-01-01
      • 2010-10-08
      • 2013-01-05
      • 2021-09-06
      相关资源
      最近更新 更多