使用JAXB灵活编组 [英] Flexible marshalling with JAXB

查看:81
本文介绍了使用JAXB灵活编组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望有一种灵活的编组方式。单个对象的详细版本和多个对象版本的详细版本。



例如,考虑我的部门模型:



获取/位置/ 1:

 < location id ='1'> 
< link rel =selfhref =http://example.com/locations/1/>
< link rel =parenthref =http://example.com/serviceareas/1/>
< name> location 01< / name>
< departments>
< department id ='1'>
< link rel =selfhref =http://example.com/departments/1/>
< name> department 01< / name>
< / department>
< department id ='2'>
< link rel =selfhref =http://example.com/departments/2/>
< name> department 02< / name>
< / department>
< department id ='3'>
< link rel =selfhref =http://example.com/departments/3/>
< name> department 03< / name>
< / department>
< / departments>
< / location>

GET / department / 1:

 < department id ='1'> 
< link rel =selfhref =http://example.com/departments/1/>
< link rel =parenthref =http://example.com/locations/1/>
< name> department 01< / name>
< abbr> dept 01< / abbr>
....
< special>重症监护< / special>
< / department>

有没有办法做到这一点?我需要有单独的实体对象吗?一个引用CRUD操作表而另一个引用列表?

解决方案

注意:我是 EclipseLink JAXB(MOXy) 领导,以及 JAXB 2(JSR-222) 专家如果您使用的是 EclipseLink JAXB(MOXy) strong>您可以利用外部绑定文档将第二个映射应用于 Department 类。






ContextResolver



JAX-RS 环境中,您可以通过 ContextResolver 来利用MOXy的外部绑定文档:

  import java.io. *; 
import java.util。*;
import javax.ws.rs.Produces;
import javax.ws.rs.ext。*;
import javax.xml.bind。*;
import org.eclipse.persistence.jaxb.JAXBContextFactory;

@Provider
@Produces({application / xml,application / json})
公共类DepartmentContextResolver实现ContextResolver< JAXBContext> {

private JAXBContext jc;

public DepartmentContextResolver(){
try {
Map< String,Object> props = new HashMap< String,Object>(1);
props.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY,example / bindings.xml);
jc = JAXBContext.newInstance(new Class [] {Department.class},props);
} catch(JAXBException e){
抛出新的RuntimeException(e);
}
}

public JAXBContext getContext(Class<?> clazz){
if(Department.class == clazz){
return jc ;
}
返回null;
}


}

更多信息








外部装订文件



默认情况下,MOXy的外部绑定文档用于扩充带注释的模型,但如果设置 xml-mapping-metadata-complete 标志,它将完全覆盖允许您的注释应用完全不同的映射:

 < xml-bindings 
xmlns =http://www.eclipse .ORG /的EclipseLink / XSD文件/持续ence / oxm
package-name =example
xml-mapping-metadata-complete =true>
...
< / xml-bindings>

更多信息





更新



此更新旨在解答您在一条评论中提出的一些问题:


1。每个ContentResolver应该/可以拥有自己的绑定文件吗?


是每个 ContextResolver 应该有自己的绑定文件。引入新的 ContextResolver 的主要原因是表示辅助映射。


2。我可以为每个ContentResolver设置多个(这会给我一些同一个类的渲染,创建一个'视图'的排序),也许在构造函数中指定它的位置?


对于单个 ContextResolver ,您可以在多个绑定文件中表达元数据,但它们将合并为一组映射。这意味着单个 ContentResolver 不能拥有单个类的多个视图。单独的 ContextResolver 用于表示辅助映射。


3。绑定文件应该驻留在哪里?


我建议从类路径加载元数据文件。






4。我可以看到如何在Resource的GET方法中轻松指定ContentResolver,但是如果对象嵌入另一个(JPA)对象中,如何做到这一点?在嵌入对象的getter / setter中?


你的JAX-RS实现应该拿起 ContextResolver 因为它是用 @Provider 注释的。用于类的 ContextResolver 将取决于您如何实现 getContext 方法:

  public JAXBContext getContext(Class<?> clazz){
if(Customer.class == clazz){
return jc;
}
返回null;
}


I'm hoping to have a flexible way of marshalling objects. A verbose version for single objects and a less-verbose version for multiple object versions.

For example, consider my department model:

GET /locations/1:

  <location id='1'>
    <link rel="self" href="http://example.com/locations/1"/>
    <link rel="parent" href="http://example.com/serviceareas/1"/>
    <name>location 01</name>
    <departments>
      <department id='1'>
        <link rel="self" href="http://example.com/departments/1"/>
        <name>department 01</name>
      </department>
      <department id='2'>
        <link rel="self" href="http://example.com/departments/2"/>
        <name>department 02</name>
      </department>
      <department id='3'>
        <link rel="self" href="http://example.com/departments/3"/>
        <name>department 03</name>
      </department>
    </departments>
  </location>

GET /department/1:

<department id='1'>
  <link rel="self" href="http://example.com/departments/1"/>
  <link rel="parent" href="http://example.com/locations/1"/>
  <name>department 01</name>
  <abbr>dept 01</abbr>
  ....
  <specialty>critical care</specialty>
</department>

Is there a way to do this? Would I need to have separate entity objects? One that references the table for CRUD operations and another for lists?

解决方案

Note: I'm the EclipseLink JAXB (MOXy) lead, and a member of the JAXB 2 (JSR-222) expert group.

Your question is tagged EclipseLink, if you are using EclipseLink JAXB (MOXy) you can take advantage of the external binding document to apply a second mapping to the Department class.


ContextResolver

In a JAX-RS environment you can leverage MOXy's external binding document through a ContextResolver:

import java.io.*;
import java.util.*;     
import javax.ws.rs.Produces;
import javax.ws.rs.ext.*;
import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.JAXBContextFactory;

@Provider
@Produces({"application/xml", "application/json"})
public class DepartmentContextResolver implements ContextResolver<JAXBContext> {

    private JAXBContext jc;

    public DepartmentContextResolver() {
        try {
            Map<String, Object> props = new HashMap<String, Object>(1);
            props.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, "example/bindings.xml");
            jc = JAXBContext.newInstance(new Class[] {Department.class} , props);
        } catch(JAXBException e) {
            throw new RuntimeException(e);
        } 
    }

    public JAXBContext getContext(Class<?> clazz) {
        if(Department.class == clazz) {
            return jc;
        }
        return null;
    }


} 

For More Information


External Binding Document

By default MOXy's external binding document is used to augment the annotated model, but if you set the xml-mapping-metadata-complete flag it will completely override the annotations allowing you to apply a completely different mapping:

<xml-bindings
    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    package-name="example"
    xml-mapping-metadata-complete="true">
    ...
</xml-bindings>

For More Information

UPDATE

This update is to address a number of questions you asked in one of your comments:

1 . Should/can each ContentResolver have its own binding file?

Yes each ContextResolver should have its own binding file. The main reason for introducing a new ContextResolver is to represent a secondary mapping.

2 . Can I have more than one for each ContentResolver (this would give me a number of renderings of the same class, creating a 'view' of sorts), perhaps specifying its location in the constructor?

For a single ContextResolver you can express the metadata across multiple binding files, but they will be combined into a single set of mappings. This means that a single ContentResolver cannot have multiple views of a single class. A separate ContextResolver is used to represent a secondary mapping.

3 . Where should the binding files reside?

I recommend loading the metadata file from the class path.

4 . I can see how the ContentResolver could be easily specified in a Resource's GET method, but how would this be done if the object is embedded in another (JPA) object? In the embedded object's getter/setter?

Your JAX-RS implementation should pick up your ContextResolver because it is annotated with @Provider. The ContextResolver used for a class will depend on how you implement the getContext method:

public JAXBContext getContext(Class<?> clazz) {
    if(Customer.class == clazz) {
        return jc;
    }
    return null;
}

这篇关于使用JAXB灵活编组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆