JAXB纯粹从接口编组 [英] JAXB marshalling purely from interfaces
问题描述
我有一个复杂的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屋!