使用 JAXB 进行灵活编组

发布于 2025-01-01 23:52:15 字数 1356 浏览 4 评论 0原文

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

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

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>

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

墨洒年华 2025-01-08 23:52:15

注意:我是EclipseLink JAXB (MOXy) 领导者,以及 JAXB 2 成员(JSR-222)专家组。

您的问题被标记为 EclipseLink,如果您使用 EclipseLink JAXB (MOXy),您可以利用外部绑定文档将第二个映射应用到 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"})
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;
    }


} 

了解更多信息


外部绑定文档

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

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

了解更多信息

更新

此更新是为了解决您在评论中提出的一些问题:

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

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

2.我可以为每个 ContentResolver 提供多个(这将为我提供同一类的多个渲染,创建某种“视图”),也许在构造函数中指定其位置?

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

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

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

4.我可以看到如何在资源的 GET 方法中轻松指定 ContentResolver,但是如果该对象嵌入到另一个 (JPA) 对象中,该怎么做?在嵌入对象的 getter/setter 中?

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

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

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;
}
丑疤怪 2025-01-08 23:52:15

这是另一个想法。可能是一个坏主意,但有点简单。

class Department {

    @XmlElement(required = true)
    public Link getSelf() {
        return self;
    }

    @XmlElement(required = false) // default
    public Link getParent() {
        if (verbose) {
            return parent;
        }
        return null;
    }

    @XmlElement(required = false) // default
    public String getSpecialty() {
        if (verbose) {
            return specialty;
        }
        return null;
    }

    @XmlTransient
    private boolean verbose;
}

Here comes another idea. Could be a bad idea but somewhat easy.

class Department {

    @XmlElement(required = true)
    public Link getSelf() {
        return self;
    }

    @XmlElement(required = false) // default
    public Link getParent() {
        if (verbose) {
            return parent;
        }
        return null;
    }

    @XmlElement(required = false) // default
    public String getSpecialty() {
        if (verbose) {
            return specialty;
        }
        return null;
    }

    @XmlTransient
    private boolean verbose;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文