【问题标题】:JAXB XML To Java MappingJAXB XML 到 Java 映射
【发布时间】:2018-02-21 14:56:06
【问题描述】:

我正在尝试将以下 XML 结构映射到一个巨大的文档中。

这是文件的一部分:

<operationQueue>
    <pick>...</pick>
    <place>...</place>
    <goTo>...</goTo>
    <toDo>...</toDo>
    ...
    <pick>...</pick>
    <place>...</place>
    <goTo>...</goTo>
    <toDo>...</toDo>    
</operationQueue>

文档中有一个 XSD 声明可以有无限制的pick、place、goTo 和 Todo 操作数组。

我想要什么,而不是为每个元素声明一个不同的数组,比如 List、List 等。

下面,我到目前为止所尝试的:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "operationQueue", propOrder = {
        "pick", "place", "goTo", "toDo"
})

public class OperationQueue {
    @XmlPath("operationQueue/pick")
    @XmlElement(name = "pick")
    public List<Pick> pick;

    @XmlPath("operationQueue/place")
    @XmlElement(name = "place")
    public List<Place> place;

    @XmlPath("operationQueue/goTo")
    @XmlElement(name = "goTo")
    public List<GoTo> goTo;

    @XmlPath("operationQueue/toDo")
    @XmlElement(name = "toDo")
    public List<oDo> toDo;
...
}

这会导致编组和解组出现问题,并使 JSON 转换的操作复杂化。 我尝试创建单个元素 QueueItem 并且每个可操作的 Item 都对其进行了增强,但我遇到了从 JSON 反序列化到 Java 对象的问题。

理想情况下,这将是一个 List&lt;QueueItem&gt;,根据 Blaise Doughan 的解决方案:Java XML and JSON Binding

@XmlAccessorType(XmlAccessType.FIELD)
public class QueueItem {
    @XmlAttribute
    private String type;

    @XmlValue
    private Object value;

但是我遇到了这个解决方案的异常:

Exception in thread "main" java.lang.NullPointerException
at com.sun.xml.internal.bind.v2.runtime.reflect.TransducedAccessor.get(TransducedAccessor.java:152)
at com.sun.xml.internal.bind.v2.runtime.property.ValueProperty.<init>(ValueProperty.java:66)
at com.sun.xml.internal.bind.v2.runtime.property.PropertyFactory.create(PropertyFactory.java:95)
at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.<init>(ClassBeanInfoImpl.java:166)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getOrCreate(JAXBContextImpl.java:488)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getOrCreate(JAXBContextImpl.java:507)
at com.sun.xml.internal.bind.v2.runtime.property.SingleElementNodeProperty.<init>(SingleElementNodeProperty.java:90)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.sun.xml.internal.bind.v2.runtime.property.PropertyFactory.create(PropertyFactory.java:113)
at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.<init>(ClassBeanInfoImpl.java:166)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getOrCreate(JAXBContextImpl.java:488)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getOrCreate(JAXBContextImpl.java:507)
at com.sun.xml.internal.bind.v2.runtime.property.ArrayElementProperty.<init>(ArrayElementProperty.java:97)
at com.sun.xml.internal.bind.v2.runtime.property.ArrayElementNodeProperty.<init>(ArrayElementNodeProperty.java:47)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.sun.xml.internal.bind.v2.runtime.property.PropertyFactory.create(PropertyFactory.java:113)
at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.<init>(ClassBeanInfoImpl.java:166)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getOrCreate(JAXBContextImpl.java:488)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getOrCreate(JAXBContextImpl.java:507)
at com.sun.xml.internal.bind.v2.runtime.property.SingleElementNodeProperty.<init>(SingleElementNodeProperty.java:90)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.sun.xml.internal.bind.v2.runtime.property.PropertyFactory.create(PropertyFactory.java:113)
at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.<init>(ClassBeanInfoImpl.java:166)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getOrCreate(JAXBContextImpl.java:488)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:305)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:124)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1123)
at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:147)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:247)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:234)
at javax.xml.bind.ContextFinder.find(ContextFinder.java:462)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:641)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:584)
at com.tideworks.tug.ecs.Main1.main(Main1.java:57)

你有什么想法如何实现一个单一的

【问题讨论】:

  • 老实说,如果你有 XSD,我建议你使用xjc 来自动生成你的 Java 代码。
  • 我愿意,我使用 jaxb2-maven-plugin 通过 XSD 生成 Java 代码,但在这种情况下,在生成的代码中,我有 OperationQueue 类,其中包含 List&lt;Object&gt; pickOrPlaceOrGotoOrTodo 字段,其中包含 List&lt;Pick&gt;、@ 987654331@里面

标签: java jaxb


【解决方案1】:

我同意大牛的观点,一般来说你应该使用 xsd。

话虽如此,但您的案例缺少上下文,可以与您提供的内容一起使用的结构可能是这样的:

您的 OperationQueue 类:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement
public class OperationQueue {

    @XmlElements({
            @XmlElement(name = "pick", type = Pick.class),
            @XmlElement(name = "place", type = Place.class),
            @XmlElement(name = "goTo", type = GoTo.class),
            @XmlElement(name = "toDo", type = ToDo.class),
    })
    public List<QueueItem> item;

}

然后 Pick、Place、GoTo 和 ToDo 类如下所示:

@XmlAccessorType(XmlAccessType.FIELD)
public class Pick implements QueueItem{
    @XmlValue
    private String value;
}

它们都实现了相同的接口,但没有多大作用:

public interface QueueItem { }

这将允许您编组/取消编组到/从呈现的 xml。

我不确定这是否适合您的情况,以及您是否可以将 xsd 更改为如下所示。但是您对 xsd 生成 List&lt;Object&gt; pickOrPlaceOrGotoOrTodo 的评论让我认为他们在创建 xsd 时也有类似的想法。

【讨论】:

  • 非常感谢您的回答,我试试您的解决方案。我觉得很好。我希望我可以更改 XSD,我会一次性解决这个问题,但我不能。
  • 谢谢你的想法,我已经改变了一点。但它一般工作正常。我已经尝试过几次类似的方法,但认为这样的解决方案行不通。
猜你喜欢
  • 2014-05-04
  • 1970-01-01
  • 1970-01-01
  • 2011-03-05
  • 1970-01-01
  • 1970-01-01
  • 2013-10-10
  • 1970-01-01
相关资源
最近更新 更多