【问题标题】:JAXB polymorphic type object marshalling like JacksonJAXB 多态类型对象编组,如 Jackson
【发布时间】:2023-03-27 21:49:01
【问题描述】:

我使用 Jackson 使用祖先类中的注释为多态对象创建 JSON:

// Include Java class name ("com.myempl.ImplClass") as JSON property "class"
@JsonTypeInfo(use=Id.CLASS, include=As.PROPERTY, property="class")

使用这个注解,后代类将拥有class 属性和对象的类名。当 Jackson 将 JSON 对象转换回正确的后代时,将使用此类名称。

将 JAX-B 与

结合使用时
@XmlSeeAlso({Class1, Class2, ... ClassN })

注解,如果要正确解组,则必须指定元素的所有子类,或者在创建新的JAXBContext 实例时将所有元素添加到JAXBContext

有没有办法像杰克逊一样为 JAX-B 指定对象类名? 如果没有办法,为什么?

【问题讨论】:

    标签: java jaxb jackson


    【解决方案1】:

    我相信您正在寻找@XmlType 注释。以下是如何使用它的示例:

    Java 模型

    import java.util.*;
    import javax.xml.bind.annotation.*;
    
    @XmlRootElement
    public class Root {
    
        private List<AbstractClass> classes = new ArrayList<AbstractClass>();
    
        @XmlElement(name="class")
        public List<AbstractClass> getClasses() {
            return classes;
        }
    
    }
    

    AbstactClass

    我们将使用@XmlSeeAlso 注释来处理Class1Class2 在计算元数据时进行处理。 Java 没有提供一种机制来反射地访问一个类的子类。

    import javax.xml.bind.annotation.XmlSeeAlso;
    
    @XmlSeeAlso({Class1.class, Class2.class})
    public class AbstractClass {
    
    }
    

    Class1

    默认情况下,每个类都有一个为短类名派生的类指示符名称。

    public class Class1 extends AbstractClass {
    
    }
    

    Class2

    我们可以使用@XmlType 注解来覆盖类指示符名称。

    import javax.xml.bind.annotation.XmlType;
    
    @XmlType(name="class-two")
    public class Class2 extends AbstractClass {
    
    }
    

    演示代码

    演示

    下面我们将创建一个Root 的实例,并在超类型AbstractClassclasses 属性上设置Class1Class2 的实例。

    import javax.xml.bind.*;
    
    public class Demo {
    
        public static void main(String[] args) throws Exception {
            JAXBContext jc = JAXBContext.newInstance(Root.class);
    
            Root root = new Root();
            root.getClasses().add(new Class1());
            root.getClasses().add(new Class2());
    
            Marshaller marshaller = jc.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.marshal(root, System.out);
        }
    
    }
    

    输出

    Class1 实例的xsi:type 值是从类名派生的,Class2 实例的值对应于我们在@XmlType 注释上设置的名称。

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <root>
        <class xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="class1"/>
        <class xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="class-two"/>
    </root>
    

    【讨论】:

    • 谢谢,但我一直在寻找一种解决方案,以避免在创建上下文时使用 @XmlSeeAlso({Class1.class, Class2.class}) 列出对象。我将对象的类名存储在一个变量中。我想知道是否有办法在解组对象而不是列出类时使用它。
    • 我最终创建了一个 JAXBContext 并使用 Guava 列出了包中的所有类,以避免在注释上手动列出类。
    猜你喜欢
    • 2016-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多