gpt4 book ai didi

java - JAXB for lists 为 JSON 或 XML 自然返回

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:53:17 24 4
gpt4 key购买 nike

我将 MOXy 与 Jersey 一起使用来实现 RESTful API,并希望自然地为 JSON 和 XML 返回列表,我的意思是 XML 包含用于整个集合以及集合项的元素标记,而JSON 仅包含集合的标签。

例如,我想返回一个包含设施和位置嵌套列表的“组织”资源。作为 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”)。

显示“设施”列表正确但“位置”不正确的 XML 示例

看到没有 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>
<id>1</id>
<kind>REGION</kind>
<name>London</name>
</locations>
<locations>
<id>2</id>
<kind>REGION</kind>
<name>Manchester</name>
</locations>
</organisation>

显示“位置”列表正确但“设施”列表不正确的 JSON 示例

看到“设施”列表是一个包含 JSON 数组的 JSON 对象,而我只想要 JSON 数组(具有复数元素名称)。

{
"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 header 以使 Jersey 返回 JSON 而不是 XML。以下是类(class)的摘录:

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;
...
}

初看起来类似于this question但我并不想在我的列表中混合对象的类型。

最佳答案

您可以执行以下操作以获得所需的 XML 和 JSON 表示形式:

第 1 步 - 利用 @XMLElementWrapper

代替:

@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):

@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 数组名称。

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;
}

}

了解更多信息

关于java - JAXB for lists 为 JSON 或 XML 自然返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20890731/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com