MOXy的对象图和动态JAXB

JAXB(JSR-222)使您可以轻松地将域类的实例转换为XML。 EclipseLink MOXy实现提供了一个称为Dynamic JAXB的扩展,在其中,您没有像真实类那样的映射实例,例如名为DynamicEntity的类。 您可以使用采用属性名称的get和set方法(即customer.get(“ address”)customer.set('name“,” Jane Doe“)来访问DynamicEntity上的数据。在本文中,我们首先将基于外部映射文件引导动态JAXBContext ,然后将XML文档解组到动态实体,最后将应用对象图来确定结果JSON输出的范围。

您可以从2013年3月24日开始从每晚下载EclipseLink 2.5.0每晚下载,以尝试这一点:

动态Java模型

对于静态模型,元数据是从Java类派生的,并通过提供的任何元数据进行扩充(请参阅: JAXB –不需要注释 )。 由于在MOXy的动态JAXB中没有域类,因此类型必须完全由元数据定义。 可以从XML模式完成此操作,也可以在本示例中使用MOXy的外部映射文档完成此操作。

oxm.xml

由于没有真正的Java类,因此在外部映射文档中,我们需要指定每个映射,并为每个映射指定Java属性的类型。

<?xml version="1.0"?>
<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    package-name="blog.objectgraphs.dynamic">
    <java-types>
        <java-type name="Customer">
            <xml-named-object-graphs>
                <xml-named-object-graph name="contact info">
                    <xml-named-attribute-node name="name"/>
                    <xml-named-attribute-node name="billingAddress" 
                        subgraph="location"/>
                    <xml-named-attribute-node name="phoneNumbers" 
                        subgraph="simple"/>
                    <xml-named-subgraph name="location">
                        <xml-named-attribute-node name="city"/>
                        <xml-named-attribute-node name="province"/>
                    </xml-named-subgraph>
                </xml-named-object-graph>
            </xml-named-object-graphs>
            <xml-root-element/>
            <java-attributes>
                <xml-attribute java-attribute="id" type="java.lang.Integer"/>
                <xml-element java-attribute="name" type="java.lang.String"/>
                <xml-element java-attribute="billingAddress" 
                    type="blog.objectgraphs.dynamic.Address"/>
                <xml-element java-attribute="shippingAddress" 
                    type="blog.objectgraphs.dynamic.Address"/>
                <xml-element 
                    java-attribute="phoneNumbers" 
                    name="phoneNumber" 
                    type="blog.objectgraphs.dynamic.PhoneNumber" 
                    container-type="java.util.List">
                    <xml-element-wrapper/>
                </xml-element>
            </java-attributes>
        </java-type>
        <java-type name="Address">
            <java-attributes>
                <xml-element java-attribute="street" type="java.lang.String"/>
                <xml-element java-attribute="city" type="java.lang.String"/>
                <xml-element java-attribute="province" type="java.lang.String"/>
                <xml-element java-attribute="postalCode" type="java.lang.String"/>
            </java-attributes>
        </java-type>
        <java-type name="PhoneNumber">
            <xml-named-object-graphs>
                <xml-named-object-graph name="simple">
                    <xml-named-attribute-node name="value"/>
                </xml-named-object-graph>
            </xml-named-object-graphs>
            <java-attributes>
                <xml-attribute java-attribute="type" type="java.lang.String"/>
                <xml-value java-attribute="value" type="java.lang.String"/>
            </java-attributes>
        </java-type>
    </java-types>
</xml-bindings>
jaxb.properties

jaxb.properties文件用于指定JAXB提供程序。 对于动态JAXB,此文件的内容与使用MOXy时的通常内容略有不同(与将EclipseLink MOXy指定为JAXB Provider相比 )。 该文件与域模型放在同一包中,因为这里有一个虚拟域模型, jaxb.properties文件将是blog.objectgraphs.dynamic包中唯一的真实项目。

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContextFactory

示范代码

下面,我们将探讨使用对象图的两种不同方法。

演示–通过元数据指定的对象图

在下面的演示代码中,我们将利用外部映射文档中定义的对象图。 为动态模型定义的对象图与为静态模型定义的对象图完全相同(请参阅: MOXy的对象图– XML和JSON的输入/输出局部模型 )。 唯一不同的是,我们从解组调用中获得的对象是DynamicEntity的实例,而不是Customer的实例。

package blog.objectgraphs.dynamic;

import java.io.File;
import java.util.*;
import javax.xml.bind.*;
import org.eclipse.persistence.dynamic.DynamicEntity;
import org.eclipse.persistence.jaxb.JAXBContextProperties;
import org.eclipse.persistence.jaxb.MarshallerProperties;

public class DemoMetadata {

    public static void main(String[] args) throws Exception {
        Map<String, Object> properties = new HashMap<String, Object>(1);
        properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, 
            "blog/objectgraphs/dynamic/oxm.xml");
        JAXBContext jc = JAXBContext.newInstance("blog.objectgraphs.dynamic", 
            DemoMetadata.class.getClassLoader(), properties);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/blog/objectgraphs/dynamic/input.xml");
        DynamicEntity customer = (DynamicEntity) unmarshaller.unmarshal(xml);

        // Output XML
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(customer, System.out);

        // Output XML - Based on Object Graph
        marshaller.setProperty(MarshallerProperties.OBJECT_GRAPH, "contact info");
        marshaller.marshal(customer, System.out);

        // Output JSON - Based on Object Graph
        marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/json");
        marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);
        marshaller.setProperty(MarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
        marshaller.marshal(customer, System.out);
    }

}
演示–以编程方式创建的对象图

在下面的演示代码中,我们将以编程方式创建对象图。 为动态模型创建的对象图与为相应静态模型创建的对象图完全相同(请参阅: MOXy的对象差距–从XML和JSON快速往返于部分模型 )。 不同之处在于,我们使用动态实体的名称而非类来创建对象图,并且从解组调用中获取了DynamicEntity的实例而不是Customer

package blog.objectgraphs.dynamic;

import java.io.File;
import java.util.*;
import javax.xml.bind.*;
import org.eclipse.persistence.dynamic.DynamicEntity;
import org.eclipse.persistence.jaxb.JAXBContextProperties;
import org.eclipse.persistence.jaxb.JAXBHelper;
import org.eclipse.persistence.jaxb.MarshallerProperties;
import org.eclipse.persistence.jaxb.ObjectGraph;
import org.eclipse.persistence.jaxb.Subgraph;

public class DemoRuntime {

    public static void main(String[] args) throws Exception {
        Map<String, Object> properties = new HashMap<String, Object>(1);
        properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, 
            "blog/objectgraphs/dynamic/oxm.xml");
        JAXBContext jc = JAXBContext.newInstance("blog.objectgraphs.dynamic", 
            DemoMetadata.class.getClassLoader(), properties);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/blog/objectgraphs/dynamic/input.xml");
        DynamicEntity customer = (DynamicEntity) unmarshaller.unmarshal(xml);

        // Output XML
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(customer, System.out);

        // Create the Object Graph
        ObjectGraph contactInfo = JAXBHelper.getJAXBContext(jc)
            .createObjectGraph("blog.objectgraphs.dynamic.Customer");
        contactInfo.addAttributeNodes("name");
        Subgraph location = contactInfo.addSubgraph("billingAddress");
        location.addAttributeNodes("city", "province");
        Subgraph simple = contactInfo.addSubgraph("phoneNumbers");
        simple.addAttributeNodes("value");

        // Output XML - Based on Object Graph
        marshaller.setProperty(MarshallerProperties.OBJECT_GRAPH, contactInfo);
        marshaller.marshal(customer, System.out);

        // Output JSON - Based on Object Graph
        marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/json");
        marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);
        marshaller.setProperty(MarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
        marshaller.marshal(customer, System.out);
    }

}

输入输出

对于元数据驱动的演示和程序化演示,以下输入和输出相同。

input.xml /输出

我们将使用以下文档来填充我们的域模型。 我们还将撤回封送它,以证明所有内容均已实际映射。

<?xml version="1.0" encoding="UTF-8"?>
<customer id="123">
   <name>Jane Doe</name>
   <billingAddress>
      <street>1 A Street</street>
      <city>Any Town</city>
      <province>Ontario</province>
      <postalCode>A1B 2C3</postalCode>
   </billingAddress>
   <shippingAddress>
      <street>2 B Road</street>
      <city>Another Place</city>
      <province>Quebec</province>
      <postalCode>X7Y 8Z9</postalCode>
   </shippingAddress>
   <phoneNumbers>
      <phoneNumber type="work">555-1111</phoneNumber>
      <phoneNumber type="home">555-2222</phoneNumber>
   </phoneNumbers>
</customer>
基于对象图的XML输出

下面的XML由与先前XML文档完全相同的模型生成。 不同之处在于,我们利用对象图来选择映射内容的子集。

<?xml version="1.0" encoding="UTF-8"?>
<customer>
   <name>Jane Doe</name>
   <billingAddress>
      <city>Any Town</city>
      <province>Ontario</province>
   </billingAddress>
   <phoneNumbers>
      <phoneNumber>555-1111</phoneNumber>
      <phoneNumber>555-2222</phoneNumber>
   </phoneNumbers>
</customer>
基于对象图的JSON输出

以下是与先前以JSON表示的XML文档相同的子集。 我们使用了新的JSON_WRAPPER_AS_ARRAY_NAME属性(请参阅绑定到JSON&XML –处理集合 )来改善集合值的表示形式。

{
   "name" : "Jane Doe",
   "billingAddress" : {
      "city" : "Any Town",
      "province" : "Ontario"
   },
   "phoneNumbers" : [ "555-1111", "555-2222" ]
}

参考: Java XML和JSON绑定博客中的JCG合作伙伴 Blaise Doughan的MOXy的对象图和动态JAXB

翻译自: https://www.javacodegeeks.com/2013/04/moxys-object-graphs-dynamic-jaxb.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果你已经检查了上面提到的几个问题,但是JAXBContext.newInstance()方法仍然抛出空指针异常,可能是由于其他原因导致的。这时,你可以尝试以下几个解决方案: 1. 检查JAXB实现是否可用 JAXBContext是JAXB API的核心类,它需要依赖JAXB实现来完成Java对象与XML之间的转换。如果JAXB实现不可用或版本不兼容,就会导致JAXBContext.newInstance()方法抛出空指针异常。建议检查项目中是否引入了正确版本的JAXB实现,并且JAXB实现是否配置正确。 2. 检查Java对象是否符合JAXB规范 JAXB规范要求Java对象必须符合一定的规范,例如必须包含默认构造函数、必须使用JAXB注解等。如果Java对象不符合JAXB规范,就会导致JAXBContext无法创建上下文。建议检查Java对象是否符合JAXB规范,并且是否正确使用了JAXB注解。 3. 尝试使用不同的JAXB实现 如果你已经检查了JAXB实现的可用性和Java对象的符合性,但是JAXBContext.newInstance()方法仍然抛出空指针异常,可以尝试使用不同的JAXB实现。例如,如果你使用的是JDK自带的JAXB实现,可以尝试使用其他第三方JAXB实现,例如Moxy或XStream等。 4. 使用其他方式实现Java对象与XML之间的转换 如果以上解决方案都无法解决问题,你可以考虑使用其他方式实现Java对象与XML之间的转换。例如,可以使用XML解析器和DOM/SAX API手动解析XML文档,或者使用其他第三方XML处理库,例如Jackson或Gson等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值