JAXB纯粹从接口编组 [英] JAXB marshalling purely from interfaces

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

问题描述

我有一个复杂的Java接口层次结构,我想用JAXB编组(而不一定是unmarshal)。这些接口表示将从JAX-RS REST API返回的对象,如XML,JSON,YAML等。(我正在使用RestEasy,它可以用XML以外的格式封送JAXB注释类型。)

I have a complex hierarchy of Java interfaces that I'd like to marshal (and not necessarily unmarshal) with JAXB. These interfaces represent objects that will be returned from a JAX-RS REST API as XML, JSON, YAML, etc. (I'm using RestEasy, which can marshal JAXB-annotated types in formats other than XML.)

问题似乎是JAXB基本上是面向类的。我已经对JAXB和接口的困难进行了大量的网络研究,最接近的解决方案是 MOXy JAXB - 将接口映射到XML JAXB和界面前端模型。但是,我有两个主要问题:a)我想在接口方面注释/工作,而不是具体的类(其中将有多个实现并包含不应该被编组的重要的其他状态),以及b)我有多级接口继承。这是接口的示例,减去目前为止的任何JAXB注释:

The problem seems to be that JAXB is fundamentally class-oriented. I've done lots of web research on the difficulties with JAXB and interfaces, the closest solutions being MOXy JAXB - Map Interfaces to XML and JAXB and Interface Fronted Models. However, I have two main issues: a) I want to annotate/work in terms of interfaces, not the concrete classes (of which there will be multiple implementations and containing significant other state that should not be marshaled), and b) I have multiple levels of interface inheritance. Here's a sample of the interfaces, minus any JAXB annotations so far:

interface Uuided {
  UUID getId();
}
interface Named {
  String getName();
}
interface Component extends Uuided, Named {
  Map<String, ComponentAttribute> getAttributes();
}
interface Attribute extends Named {
  Type getType();
  Object getValue();
}
interface ComponentAttribute extends Attribute {
  Component getDeclaringComponent();
}

理想情况下,这会生成以下内容:

Ideally, this would generate something like:

<component id="xxx" name="thing">
  <attributes>
    <componentAttribute name="color">
      <type><stringType/></type>
      <value>green</value>
      <declaringComponent idref="xxx"/>
    </componentAttribute>
  </attributes>
</component>

显然,在抽象中,这会导致诸如确定最派生的带注释的界面之类的问题,其中有理论上可以不止一个。但是,在我的情况下,我认为具体类只实现了一个应该被封送的单个接口。解组不是必需的,因为我有单独的类定义upsert属性。

Clearly, in the abstract, this leads to issues like determining the most derived annotated interface, of which there could theoretically be more than one. In my case, however, I believe the concrete classes only implement a single interface that should be marshaled. Unmarshaling is not necessary, as I have separate classes defining upsert properties.

所以我的问题是,这甚至可以用JAXB来处理,如果是这样,怎么样?即使我必须非常明确地定义绑定,适配器等,我也希望在JAXB框架内工作以获得RestEasy中所有非XML提供程序的好处。

So my question is, is this even possible to handle with JAXB, and if so, how? Even if I have to be very explicit in defining bindings, adapters, etc., I'd like to work within the JAXB framework to get the benefit of all the non-XML providers in RestEasy.

推荐答案

我认为答案是JAXB根本不打算支持这个,并且尝试强制它是愚蠢的。此外,JAXB驱动的JSON编组也不是理想的。

I think the answer is that JAXB isn't at all intended to support this and that it's foolish to try to force it. Also, JAXB-driven JSON marshaling turns out not to be ideal either.

我最终编写了自己的编组框架,并附带了一组注释:

I ended up writing my own marshaling framework, with its own set of annotations:

@MarshalMixin // marshal fields but not a top-level object
interface Uuided {
  @MarshalAsString // ignore properties; just call toString()
  @MarshalId // treat as identifier for @MarshalUsingIds or cyclic ref
  UUID getId();
}
@MarshalMixin
interface Named {
  @MarshalId
  String getName();
}
@MarshalObject // top-level marshaled object providing class name
interface Component extends Uuided, Named {
  @MarshalAsKeyedObjectMap(key = "name") // see description below
  Map<String, ComponentAttribute> getAttributes();
}
@MarshalObject
interface Attribute extends Named {
  Type getType();
  @MarshalDynamic // use run-time (not declared) type
  Object getValue();
}
interface ComponentAttribute extends Attribute {
  @MarshalUsingIds
  Component getDeclaringComponent();
}

生成的封送程序写入抽象层(当前为JSON和XML实现) 。这样可以提供更大的灵活性,使输出在不需要大量注释和适配器的情况下适用于不同的表示。例如,我正在调用键控对象映射,其中每个对象都包含其映射键。在JSON中,您需要一个地图,但在XML中,您需要一个序列:

The generated marshalers write to an abstraction layer (currently implemented for JSON and XML). This gives a lot more flexibility to make the output natural for different representations without a ton of annotations and adapters. E.g., what I'm calling keyed-object maps, where each object contains its map key. In JSON, you want a map, but in XML, you want a sequence:

{..., map: {'a': {'name': 'a', ...}, 'b': {'name: 'b', ...}, ...}, ...}
...<map><thing name='a'>...</thing><thing name='b'>...</thing></map>...

似乎有多达4个人也关心这个,所以希望我最终可以开源。 : - )

Seems like as many as 4 other people care about this too, so hopefully I can open-source it eventually. :-)

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

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