java - 如何使用 XStream 将同名节点反序列化为两个不同的类

标签 java xml xstream

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

我的文件是这样的:

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

我有一个名为Alternative 的类(class):

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

该类由另外两个类扩展:

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

关于java - 如何使用 XStream 将同名节点反序列化为两个不同的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44928699/

相关文章:

android - 1个imageview android上的多个动画

xml - 'packages' 元素未声明

java - 如何使用 xstream 将 Hashmap 映射到 XML 中的键值属性

java - 在 xstream 中反序列化旧版 XML 结构

java - 将 xstream 与 mysql 一起使用

Java Amazon S3 Post 表单

java - 安装 Apache Maven

java - Spring 3 对象与原始数据类型的绑定(bind)列表

java - 如何打印数组的三种不同类型的对象(其中可以存储任何类型的对象)并将其打印在单独的数组中?

c# - 在可序列化的 C# 类上使用不带 XmlArray 的 XmlArrayItem 属性