JAXB:Unmarshal异构数组

时间:2015-05-11 10:39:20

标签: java json jaxb unmarshalling moxy

我正在尝试使用具有以下结构的MOXy解组:

[
  {
    "page": 1,
    "pages": 1
  },
  [
    {
        "indicator": {
            "id": "IC.BUS.EASE.XQ",
            "value": "Ease of doing business index"
        },
        "country": {
            "id": "1A",
            "value": "Arab World"
        },
        "value": "113.952380952381",
        "date": "2014"
    },
    ...
    ]
]

数组的第一个元素是一个对象,第二个元素是另一个复杂元素数组。我真的在SO和MOXy文档中搜索了一个类似的例子但没有任何成功。

我将json文档映射到JAVA类的最佳尝试如下。根类是CountryDataResponse(getters& setters ommited):

@XmlRootElement
@XmlType(propOrder ={"paginationInfo", "dataArray"})
public class CountryDataResponse {
    private DataArray dataArray;
    private PaginationInfo paginationInfo;
}

(我可以看到这会失败,因为它不是一个数组,但我完全失败了。)

PaginationInfo类为根数组的第一个元素建模,DataArray类包装第二个元素,它是一个Data类元素数组。另外,我为每个Data元素中的复杂类型创建了Indicator和Country类。

主要类别(指标和国家省略):

@XmlRootElement(name = "paginationInfo")
@XmlAccessorType(XmlAccessType.FIELD)
public class PaginationInfo {

    private int page;
    private int pages;
}
@XmlRootElement( name = "dataArray" )
public class DataArray {
    List<Data> datas;
}
@XmlRootElement(name="data")
@XmlAccessorType(XmlAccessType.FIELD)
public class Data {
    private Indicator indicator;
    private Country country;
    private String date;
    private double value;
}

现在,调试以下代码:

public static void main(String args[]) {
    String test = "[{\"page\": 1,\"pages\": 1,\"per_page\": \"1000\",\"total\": 248},"
                + "["
                + "{\"indicator\": {\"id\": \"NY.GDP.MKTP.CD\",\"value\": \"GDP (current US$)\"},"
                + "\"country\": {\"id\": \"1A\",\"value\": \"Arab World\"},"
                + "\"value\": \"2853079422103.94\","
                + "\"decimal\": \"1\","
                + "\"date\": \"2013\"},"
                + "{\"indicator\": {\"id\": \"NY.GDP.MKTP.CD\",\"value\": \"GDP (current US$)\"},"
                + "\"country\": {\"id\": \"S3\",\"value\": \"Caribbean small states\"},"
                + "\"value\": \"67033118185.1864\","
                + "\"decimal\": \"1\","
                + "\"date\": \"2013\"}"
                + "]]";

    JAXBContext jc = JAXBContext.newInstance(CountryDataResponse.class, Country.class, Data.class, DataArray.class, Indicator.class, PaginationInfo.class);
    Unmarshaller unmarshaller = jc.createUnmarshaller();
    unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, MediaType.APPLICATION_JSON);
    unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);

    Object res = unmarshaller.unmarshal(json, CountryDataResponse.class);
}

res对象(类JAXBElement)的值类型为ArrayList 。数组第一个元素类CountryDataResponse的对象 应该是PaginationInfo ),第二个是另一个 ArrayList ,其元素 CountryDataResponse (他们应该 数据实例)。

任何人都可以帮助我,或者它只是一个格式错误的json,它不能自动解组正确吗?

提前谢谢。

2 个答案:

答案 0 :(得分:1)

虽然JSON有效但我建议改变结构,类似于:

{
"paginationInfo": {
    "page": 1,
    "pages": 1
},
"dataArray": [
    {
        "indicator": {
            "id": "IC.BUS.EASE.XQ",
            "value": "Ease of doing business index"
        },
        "country": {
            "id": "1A",
            "value": "Arab World"
        },
        "value": "113.952380952381",
        "date": "2014"
    }
]

}

这将允许您使用&#39;键提取您想要的数据。名称是JSON的使用方式。

另一种方法是将数据数组嵌入分页对象中:

{
"page": 1,
"pages": 1,
"dataArray": [
    {
        "indicator": {
            "id": "IC.BUS.EASE.XQ",
            "value": "Ease of doing business index"
        },
        "country": {
            "id": "1A",
            "value": "Arab World"
        },
        "value": "113.952380952381",
        "date": "2014"
    }
]

}

这种方法可以让你创建一个通用的页面包装器,如果你有多种格式要打页,它可能会很有用。

希望这会有所帮助。

答案 1 :(得分:0)

由于版本2.6中添加了MOXy的功能,因此可以从javax.json.JsonStructure,javax.json.JsonObject和javax.json.JsonArray解组。

使用此功能,我设法将原始JSON的不同部分解组为两个对象:PaginationInfo实例和DataList的ArrayList。然后可以使用这些对象来配置CountryDataResponse的实例,尽管没有必要,因为这个类只是为了尝试直接从JSON解组而创建的。

public static CountryDataResponse javaSevenMode(String jsonString) 
    throws PropertyException, JAXBException {

    Unmarshaller unmarshaller = JAXB_CONTEXT.createUnmarshaller();
    unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, MediaType.APPLICATION_JSON);
    unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);

    StringReader sr = new StringReader(jsonString);
    JsonReader jsonReader = Json.createReader(sr);
    JsonArray rootArray = jsonReader.readArray();

    JsonObject paginationInfoJO = rootArray.getJsonObject(0);
    JsonStructureSource paginationInfoJSS = new JsonStructureSource(paginationInfoJO);
    PaginationInfo pi = unmarshaller.unmarshal(paginationInfoJSS, PaginationInfo.class).getValue();

    JsonArray dataJArray = rootArray.getJsonArray(1);
    JsonStructureSource dataArrayJSS = new JsonStructureSource(dataJArray);
    List<Data> datas
            = (List<Data>) unmarshaller.unmarshal(dataArrayJSS, Data.class)
            .getValue();

    DataArray da = new DataArray();
    da.setDatas(datas);

    CountryDataResponse cdr = new CountryDataResponse();
    cdr.setDataArray(da);
    cdr.setPaginationInfo(pi);

    return cdr;
}

感谢@blaise-doughan获取灵感(请参阅http://blog.bdoughan.com/2013/07/eclipselink-moxy-and-java-api-for-json.html