JAXB用于为JSON或XML自然返回的列表 [英] JAXB for lists to be returned naturally for JSON or XML
问题描述
我正在使用MOXy和Jersey实现一个RESTful API,并希望自然地为JSON和XML返回列表,我的意思是XML包含整个集合的元素标记以及集合项,而JSON仅包含集合的标记。
I'm using MOXy with Jersey to implement a RESTful API and want to return lists naturally for JSON and XML, by which I mean that the XML contains an element tag for the overall collection as well as the collection items, whereas the JSON contains a tag for the collection only.
例如,我想返回一个组织资源,其中包含设施和位置的嵌套列表。作为XML:
For example, I want to return an "organisation" resource with nested lists of facilities and locations. As XML:
<organisation>
<id>1</id>
<name>XYZ</name>
<facilities>
<facility>
<id>1</id>
<text>Telephone</text>
</facility>
<facility>
<id>3</id>
<text>Whiteboard</text>
</facility>
</facilities>
<locations>
<location>
<id>1</id>
<kind>REGION</kind>
<name>London</name>
</location>
<location>
<id>2</id>
<kind>REGION</kind>
<name>Manchester</name>
</location>
</locations>
</organisation>
以及JSON:
{
"id": 1,
"name": "XYZ",
"facilities": [
{
"id": 1,
"text": "Telephone"
},
{
"id": 3,
"text": "Whiteboard"
}
],
"locations": [
{
"id": 1,
"kind": "REGION",
"name": "London"
},
{
"id": 2,
"kind": "REGION",
"name": "Manchester"
}
]
}
不幸的是,我似乎没有能够获得一个代码库,允许我为XML和JSON返回这样的输出。如果我使用一个类来包装嵌套列表,那么XML看起来是正确的但不是JSON(参见下面的ExternalFacilities)。如果我将嵌套列表定义为 ArrayList
子类,则JSON显示正确但不是XML(请参阅下面的ExternalLocations)。
Unfortunately, I don't seem to be able to get a code base that allows me to return the output like this for both XML and JSON. If I use a class to wrap the nested list, then the XML appears correct but not the JSON (see "ExternalFacilities" below). If I define the nested list as an ArrayList
sub-class then the JSON appears correct but not the XML (see "ExternalLocations" below).
显示设施列表正确但不是位置的XML示例
看到没有XML元素包装位置列表(就像设施一样),并且每个位置都有一个复数元素名称。
See that there is no XML element that wraps the "locations" list (as there is for "facilities"), and also that each location has a pluralised element name.
<organisation>
<id>1</id>
<name>XYZ</name>
<facilities>
<facility>
<id>1</id>
<text>Telephone</text>
</facility>
<facility>
<id>3</id>
<text>Whiteboard</text>
</facility>
</facilities>
<locations>
<id>1</id>
<kind>REGION</kind>
<name>London</name>
</locations>
<locations>
<id>2</id>
<kind>REGION</kind>
<name>Manchester</name>
</locations>
</organisation>
JSON示例显示位置列表正确但不是设施
看到facility列表是一个包含JSON数组的JSON对象,而我只想要JSON数组(带有复数元素名称)。
See that the "facilities" list is a JSON object containing a JSON array, whereas I just want the JSON array (with the pluralised element name).
{
"id": 1,
"name": "XYZ",
"facilities": {
"facility": [
{
"id": 1,
"text": "Telephone"
},
{
"id": 3,
"text": "Whiteboard"
}
]
},
"locations": [
{
"id": 1,
"kind": "REGION",
"name": "London"
},
{
"id": 2,
"kind": "REGION",
"name": "Manchester"
}
]
}
以上示例使用相同的代码生成,只需更改Accept HTTP标头即可让Jersey返回JSON XML。以下是课程的摘录:
This samples above are produced using the same code, just changing the Accept HTTP header to have Jersey return JSON instead of XML. Here is an excerpt of the classes:
ExternalOrganisation.java
@XmlRootElement(name="organisation")
@XmlAccessorType(XmlAccessType.FIELD)
public class ExternalOrganisation {
private String name;
private ExternalFacilities facilities;
private ExternalLocations locations;
...
}
ExternalFacilities.java
@XmlRootElement(name="facilities")
public class ExternalFacilities {
@XmlElementRef
private List<ExternalFacility> list;
...
}
ExternalLocations.java
@XmlRootElement(name="locations")
public class ExternalLocations extends ArrayList<ExternalLocation> {
...
}
ExternalFacility.java
@XmlRootElement(name="facility")
@XmlType(propOrder={"id", "uri", "kind", "text"})
public class ExternalFacility extends ExternalBase {
// id inherited
private String text;
....
}
ExternalLocation.java
@XmlRootElement(name="location")
@XmlType(propOrder={"id", "kind", "name"})
public class ExternalLocation extends ExternalBase {
// id inherited
@XmlElement private LocationKind kind;
@XmlElement private String name;
...
}
最初似乎与这个问题,但我不是在尝试混合我列表中的对象类型。
Seems at first similar to this question but I'm not trying to mix the types of object in my lists.
推荐答案
您可以执行以下操作来获取所需的XML和JSON表示:
You could do the following to get the desired XML and JSON representations:
of:
@XmlRootElement(name="organisation")
@XmlAccessorType(XmlAccessType.FIELD)
public class ExternalOrganisation {
private String name;
private ExternalFacilities facilities;
private ExternalLocations locations;
...
}
你可以使用 @XmlElementWrapper
执行以下操作(请参阅: http://blog.bdoughan.com/2010/09/jaxb-collection-properties.html ):
You could do the following with @XmlElementWrapper
(see: http://blog.bdoughan.com/2010/09/jaxb-collection-properties.html):
@XmlRootElement(name="organisation")
@XmlAccessorType(XmlAccessType.FIELD)
public class ExternalOrganisation {
private String name;
@XmlElementWrapper
@XmlElementRef
private List<ExternalFacility> facilities;
@XmlElementWrapper
@XmlElementRef
private List<ExternalLocation> locations;
...
}
步骤#2 - 利用MOXy的包装器作为数组名称属性
通过将包装器指定为数组名称属性,MOXy将使用 @XmlElementWrapper
作为JSON数组名称。
Step #2 - Leverage MOXy's Wrapper as Array Name Property
By specifying the wrapper as array name property, MOXy will use the value from @XmlElementWrapper
as the JSON array name.
import java.util.*;
import javax.ws.rs.core.Application;
import org.eclipse.persistence.jaxb.rs.MOXyJsonProvider;
public class YourApplication extends Application {
@Override
public Set<Class<?>> getClasses() {
HashSet<Class<?>> set = new HashSet<Class<?>>(1);
set.add(YourService.class);
return set;
}
@Override
public Set<Object> getSingletons() {
MOXyJsonProvider moxyJsonProvider = new MOXyJsonProvider();
moxyJsonProvider.setWrapperAsArrayName(true);
HashSet<Object> set = new HashSet<Object>(1);
set.add(moxyJsonProvider);
return set;
}
}
更多信息
- http://blog.bdoughan.com/2013/03/binding-to-json-xml-handling-collections.html
- http:// blog .bdoughan.com / 2013/06 / moxy-is-new-default-json-binding.html
- http://blog.bdoughan.com/2013/03/binding-to-json-xml-handling-collections.html
- http://blog.bdoughan.com/2013/06/moxy-is-new-default-json-binding.html
这篇关于JAXB用于为JSON或XML自然返回的列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!