如何将同名节点反序列化为两个不同的 类 和 XStream

How to deserialize same name node into two different classes with XStream

我在反序列化 XML 文件时遇到问题。

我的文件是这样的:

<mission>
    <branch>
        <alternative uid="0" type="ALT_MONITOR"/>
        <alternative uid="1" type="ALT_IF" condition="i==10"/>
    </branch>
</mission>

我有一个 class 叫做 Alternative:

public abtract class Alternative {
    @XStreamAsAttribute
    public int uid;
    @XStreamAsAttribute
    public String type;
}

此 class 由另外两个 class 扩展:

@XStreamAlias("alternative")
public class AlternativeA extends Alternative {
}

@XStreamAlias("alternative")
public class AlternativeB extends Alternative {
    @XStreamAsAttribute
    public String condition;
}

然后我有一个 xStream 转换器 :

public class AlternativeConverter extends ReflectionConverter {
    public AlternativesConverter(Mapper mapper, ReflectionProvider reflectionProvider) {
        super(mapper, reflectionProvider);
    }

    @Override
    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
    if (reader.getAttribute("condition") != null) {
    AlternativeA alternativeA = new AlternativeA();
    alternativeA.setUid(Integer.parseInt(reader.getAttribute("uid")));
    alternativeA.setCondition(reader.getAttribute("condition"));
    return super.doUnmarshal(alternativeA, reader, context);
    }else {
    AlternativeB alternativeB = new AlternativeB();
    alternativeB.setUid(Integer.parseInt(reader.getAttribute("uid")));
    return super.doUnmarshal(alternativeB, reader, context);
    }
    }

     @SuppressWarnings("unchecked")
     @Override
     public boolean canConvert(Class clazz) {
        return Alternative.class.isAssignableFrom(clazz);
    }
}

但是当我尝试将 xml 转换为对象时。当它到达有条件的备选方案时,它会抛出异常:

Cannot convert type AlternativeB to type AlternativeA

你们中的任何人对可能导致该错误的原因有任何想法或见解吗? 提前谢谢你。

Java:

package de.mosst.spielwiese;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.junit.Test;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.converters.reflection.ReflectionConverter;
import com.thoughtworks.xstream.converters.reflection.ReflectionProvider;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.mapper.Mapper;

import lombok.Data;

public class XStreamMultiClassesTest {

    @Test
    public void smokeTest() {
        InputStream file = XStreamMultiClassesTest.class.getResourceAsStream("XStreamMultiClassesTest.xml");
        XStream xStream = new XStream();
        xStream.ignoreUnknownElements();
        xStream.processAnnotations(Mission.class);
        xStream.processAnnotations(Alternative.class);

        Converter converter = new AlternativeConverter(xStream.getMapper(), xStream.getReflectionProvider());
        xStream.registerConverter(converter);

        Mission mission = (Mission) xStream.fromXML(file);

        System.out.println(mission);
        mission.branch.forEach(a -> {
            System.out.println(a.getClass());
            if (a instanceof AlternativeA) {
                System.out.println("- condition: " + ((AlternativeA) a).condition);
            }
        });
    }

    public class AlternativeConverter extends ReflectionConverter {

        public AlternativeConverter(Mapper mapper, ReflectionProvider reflectionProvider) {
            super(mapper, reflectionProvider);
        }

        @Override
        public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
            Alternative alternative = null;
            if (reader.getAttribute("condition") != null) {
                alternative = new AlternativeA();
                ((AlternativeA) alternative).condition = reader.getAttribute("condition");
            } else {
                alternative = new AlternativeB();
            }
            alternative.uid = Integer.parseInt(reader.getAttribute("uid"));
            return super.doUnmarshal(alternative, reader, context);
        }

        @Override
        public boolean canConvert(@SuppressWarnings("rawtypes") Class clazz) {
            return Alternative.class.isAssignableFrom(clazz);
        }
    }

    @XStreamAlias("mission")
    @Data
    class Mission {
        public List<Alternative> branch = new ArrayList<>();
    }

    @XStreamAlias("alternative")
    @Data
    abstract class Alternative {
        @XStreamAsAttribute
        public int uid;
        @XStreamAsAttribute
        public String type;
    }

    class AlternativeA extends Alternative {
        public String condition;
    }

    class AlternativeB extends Alternative {
    }

}

XML:

<?xml version="1.0" encoding="UTF-8"?>
<mission>
    <branch>
        <alternative uid="0" type="ALT_MONITOR" />
        <alternative uid="1" type="ALT_IF" condition="i==10" />
    </branch>
</mission>