JAXB:解组异构数组
JAXB: Unmarshal heterogeneous array
我正在尝试使用具有以下结构的 MOXy a json 解组:
[
{
"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 classes 的最佳尝试如下。根 class 是 CountryDataResponse(省略了 getters 和 setters):
@XmlRootElement
@XmlType(propOrder ={"paginationInfo", "dataArray"})
public class CountryDataResponse {
private DataArray dataArray;
private PaginationInfo paginationInfo;
}
(我知道这会失败,因为它不是数组,但我完全迷路了。)
PaginationInfo class 对根数组的第一个元素建模,DataArray class 包装第二个元素,这是一个数据数组 class 元素。此外,我还为每个数据元素内的复杂类型创建了 Indicator 和 Country classes。
主要classes(省略指标和国家/地区):
@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 对象(属于 class JAXBElement)有一个 ArrayList 类型的值。数组的第一个元素是classCountryDataResponse的一个对象(它应该是PaginationInfo),第二个是另一个ArrayList,元素是of class CountryDataResponse,也是(他们应该 是 Data 实例)。
任何人都可以帮助我吗,或者它只是格式错误 json 并且无法正确自动解组?
提前谢谢你。
尽管 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"
}
]
}
这将允许您使用 'key' 名称提取您想要的数据,这正是 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"
}
]
}
这种方法可以让您创建一个通用的页面包装器,如果您有多种格式要分页,它会很有用。
希望这对您有所帮助。
感谢 2.6 版中添加的 MOXy 功能,可以从 javax.json.JsonStructure、javax.json.JsonObject 和 javax.json.JsonArray 解组。
使用此功能,我设法将原始 JSON 的不同部分解组为两个对象:一个 PaginationInfo 实例和一个 ArrayList 数据。然后可以使用这些对象来配置 CountryDataResponse 的实例,尽管这不是必需的,因为首先创建此 class 只是为了尝试直接从 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 for inspiration (see http://blog.bdoughan.com/2013/07/eclipselink-moxy-and-java-api-for-json.html)
我正在尝试使用具有以下结构的 MOXy a json 解组:
[
{
"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 classes 的最佳尝试如下。根 class 是 CountryDataResponse(省略了 getters 和 setters):
@XmlRootElement
@XmlType(propOrder ={"paginationInfo", "dataArray"})
public class CountryDataResponse {
private DataArray dataArray;
private PaginationInfo paginationInfo;
}
(我知道这会失败,因为它不是数组,但我完全迷路了。)
PaginationInfo class 对根数组的第一个元素建模,DataArray class 包装第二个元素,这是一个数据数组 class 元素。此外,我还为每个数据元素内的复杂类型创建了 Indicator 和 Country classes。
主要classes(省略指标和国家/地区):
@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 对象(属于 class JAXBElement)有一个 ArrayList 类型的值。数组的第一个元素是classCountryDataResponse的一个对象(它应该是PaginationInfo),第二个是另一个ArrayList,元素是of class CountryDataResponse,也是(他们应该 是 Data 实例)。
任何人都可以帮助我吗,或者它只是格式错误 json 并且无法正确自动解组?
提前谢谢你。
尽管 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"
}
]
}
这将允许您使用 'key' 名称提取您想要的数据,这正是 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"
}
]
}
这种方法可以让您创建一个通用的页面包装器,如果您有多种格式要分页,它会很有用。
希望这对您有所帮助。
感谢 2.6 版中添加的 MOXy 功能,可以从 javax.json.JsonStructure、javax.json.JsonObject 和 javax.json.JsonArray 解组。
使用此功能,我设法将原始 JSON 的不同部分解组为两个对象:一个 PaginationInfo 实例和一个 ArrayList 数据。然后可以使用这些对象来配置 CountryDataResponse 的实例,尽管这不是必需的,因为首先创建此 class 只是为了尝试直接从 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 for inspiration (see http://blog.bdoughan.com/2013/07/eclipselink-moxy-and-java-api-for-json.html)