Java 为什么以及何时在 JAXB 中需要 JAXBElement?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20396375/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 01:38:56  来源:igfitidea点击:

Why and when JAXBElement is required in JAXB?

javaxmloraclejaxbxsd

提问by Aman Arora

I am just learning JAXB (Java Architecture for XML Binding). Reading through a few sources , one doubt has come in my mind regarding JAXBElement.

Oracle docs say:

我只是在学习 JAXB(用于 XML 绑定的 Java 架构)。翻阅了一些资料,我心中产生了一个疑问JAXBElement

Oracle 文档说:

When XML element information can not be inferred by the derived Java representation of the XML content, a JAXBElement object is provided. This object has methods for getting and setting the object name and object value.Link here

When XML element information can not be inferred by the derived Java representation of the XML content, a JAXBElement object is provided. This object has methods for getting and setting the object name and object value.链接在这里

Does it mean that JAXBElementneeds to be used when there is not a direct mapping between Schema defined datatype and Java data type?

这是否意味着JAXBElement在 Schema 定义的数据类型和 Java 数据类型之间没有直接映射时需要使用?

Further, In one of the code examples listed under. which i followed from here:

此外,在下面列出的代码示例之一中。我从这里遵循:

 ObjectFactory factory = new ObjectFactory();

    UserT user = factory.createUserT();
    user.setUserName("Sanaulla");
    ItemT item = factory.createItemT();
    item.setItemName("Seagate External HDD");
    item.setPurchasedOn("August 24, 2010");
    item.setAmount(new BigDecimal("6776.5"));

    ItemListT itemList = factory.createItemListT();
    itemList.getItem().add(item);

    ExpenseT expense = factory.createExpenseT();// we get expense object here
    expense.setUser(user);
    expense.setItems(itemList);

    JAXBContext context = JAXBContext.newInstance("generated");
    JAXBElement<ExpenseT> element = factory.createExpenseReport(expense);//why is this required
    Marshaller marshaller = context.createMarshaller();
    marshaller.setProperty("jaxb.formatted.output",Boolean.TRUE);
    marshaller.marshal(element,System.out);

Using ExpenseT expense = factory.createExpenseT();we are able to get ExpenseTobject.

Again in the code if we see ,we create

JAXBElement<ExpenseT> element = factory.createExpenseReport(expense);
which according to this sourceis a wrapper for expenseobject.
On the other hand we don't create wrappers for the objects retrieved using
UserT user = factory.createUserT();

So my questions are :

使用ExpenseT expense = factory.createExpenseT();我们可以获取ExpenseT对象。

再次在代码中,如果我们看到,我们

JAXBElement<ExpenseT> element = factory.createExpenseReport(expense);
根据此源创建它是expense对象的包装器。
另一方面,我们不会为使用检索的对象创建包装器
UserT user = factory.createUserT();

所以我的问题是:

  1. What is the need of JAXBElementwrapper around expense?
  2. when to use JAXBElement?
  1. 需要什么JAXBElement包装expense
  2. 什么时候使用JAXBElement

采纳答案by bdoughan

There are a few use cases where a JAXBElementis required:

有几个用例JAXBElement需要 a:

  1. An element is both nillable="true"and minOccurs="0". In this case what does nullon the mapped field/property mean? When the property is JAXBElementa null value means the element isn't present and a JAXBElementwrapping null means an XML element with xsi:nil="true".
  2. There are 2 global elements with the same named complex type. Since in JAXB classes correspond to complex types a way is needed to capture which root element was encountered.
  3. There is a choice structure where either fooor barelements can occur and they are the same type. Here a JAXBElementis required because simply encountering a Stringvalue isn't enough to indicate which element should be marshalled.
  4. An element with xsi:nilis encountered in the document that contains attributes. In this example the object corresponding to that element can still be unmarshalled to hold the attribute values, but JAXBElement can stil indicate that the element was null.
  1. 一个元素既是nillable="true"又是minOccurs="0"。在这种情况下null,映射的字段/属性是什么意思?当属性为JAXBElement空值时,表示该元素不存在,而JAXBElement包装空值表示带有xsi:nil="true".
  2. 有 2 个具有相同命名复杂类型的全局元素。由于 JAXB 类对应于复杂类型,因此需要一种方法来捕获遇到的根元素。
  3. 有一个选择结构,其中一个foobar元素可以出现并且它们是相同的类型。这里 aJAXBElement是必需的,因为仅仅遇到一个String值不足以指示应该编组哪个元素。
  4. xsi:nil在包含属性的文档中遇到了一个元素。在此示例中,与该元素对应的对象仍然可以解组以保存属性值,但 JAXBElement 仍然可以指示该元素为空。

回答by Mathias G.

JAXBElement is used to preserve the element name/namespace in use cases where enough information is not present in the object model. It's often used with substitution groups.

JAXBElement 用于在对象模型中没有足够信息的用例中保留元素名称/命名空间。它通常与替换组一起使用。

Without any JAXB metada the result will be wrapped in a JAXBElement. You can eliminates the root level JAXBElement by using the @XmlRootElement annotation.

如果没有任何 JAXB 元数据,结果将被包装在 JAXBElement 中。您可以使用 @XmlRootElement 注释消除根级别 JAXBElement。

If you use xsd files from an external source and no XmlRootElement annotation is available on the generated classes, using JAXBElement during the marshalling process can really come in handy since you can unmarshal the xml to an object using the JAXBElement wrapper. You will see that specifying the class itself doesn't work in that case...

如果您使用来自外部源的 xsd 文件并且在生成的类上没有可用的 XmlRootElement 注释,则在编组过程中使用 JAXBElement 真的会派上用场,因为您可以使用 JAXBElement 包装器将 xml 解组为对象。你会看到在这种情况下指定类本身不起作用......

This will work:

这将起作用:

JAXBElement<Object> je = (JAXBElement<Object>) unmarshaller.unmarshal(objectXML);
Object = je.getValue();

This will throw a JAXBException:

这将抛出一个 JAXBException:

Object obj = (Object) unmarshaller.unmarshal(objectXML);