JAXB用于为JSON或XML自然返回的列表 [英] JAXB for lists to be returned naturally for JSON or XML

查看:82
本文介绍了JAXB用于为JSON或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

这篇关于JAXB用于为JSON或XML自然返回的列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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