我想消費REST接口,讓下面的輸出(準確地說,我想找回TAF元素的列表):解析與Spring引導RestTemplate嵌套元素給JSON解析錯誤
<?xml version="1.0" encoding="UTF-8"?>
<response xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XML-Schema-instance" version="1.2" xsi:noNamespaceSchemaLocation="http://aviationweather.gov/adds/schema/taf1_2.xsd">
<request_index>32084191</request_index>
<data_source name="tafs" />
<request type="retrieve" />
<errors />
<warnings />
<time_taken_ms>13</time_taken_ms>
<data num_results="4">
<TAF>
<raw_text>TAF EPGD 171130Z 1712/1812 25008KT CAVOK PROB40 1718/1806 1500 BR BKN005</raw_text>
<station_id>EPGD</station_id>
<issue_time>2017-10-17T11:30:00Z</issue_time>
<bulletin_time>2017-10-17T11:00:00Z</bulletin_time>
<valid_time_from>2017-10-17T12:00:00Z</valid_time_from>
<valid_time_to>2017-10-18T12:00:00Z</valid_time_to>
<latitude>54.37</latitude>
<longitude>18.47</longitude>
<elevation_m>138.0</elevation_m>
<forecast>
<fcst_time_from>2017-10-17T12:00:00Z</fcst_time_from>
<fcst_time_to>2017-10-18T12:00:00Z</fcst_time_to>
<wind_dir_degrees>250</wind_dir_degrees>
<wind_speed_kt>8</wind_speed_kt>
<visibility_statute_mi>6.21</visibility_statute_mi>
<wx_string>NSW</wx_string>
<sky_condition sky_cover="NSC" />
</forecast>
<forecast>
<fcst_time_from>2017-10-17T18:00:00Z</fcst_time_from>
<fcst_time_to>2017-10-18T06:00:00Z</fcst_time_to>
<change_indicator>PROB</change_indicator>
<probability>40</probability>
<visibility_statute_mi>0.93</visibility_statute_mi>
<wx_string>BR</wx_string>
<sky_condition sky_cover="BKN" cloud_base_ft_agl="500" />
</forecast>
</TAF>
<TAF>
<raw_text>TAF EPGD 170530Z 1706/1806 22010KT 0300 FG BKN002 BECMG 1707/1709 CAVOK</raw_text>
<station_id>EPGD</station_id>
<issue_time>2017-10-17T05:30:00Z</issue_time>
<bulletin_time>2017-10-17T05:00:00Z</bulletin_time>
<valid_time_from>2017-10-17T06:00:00Z</valid_time_from>
<valid_time_to>2017-10-18T06:00:00Z</valid_time_to>
<latitude>54.37</latitude>
<longitude>18.47</longitude>
<elevation_m>138.0</elevation_m>
<forecast>
<fcst_time_from>2017-10-17T06:00:00Z</fcst_time_from>
<fcst_time_to>2017-10-17T07:00:00Z</fcst_time_to>
<wind_dir_degrees>220</wind_dir_degrees>
<wind_speed_kt>10</wind_speed_kt>
<visibility_statute_mi>0.19</visibility_statute_mi>
<wx_string>FG</wx_string>
<sky_condition sky_cover="BKN" cloud_base_ft_agl="200" />
</forecast>
<forecast>
<fcst_time_from>2017-10-17T07:00:00Z</fcst_time_from>
<fcst_time_to>2017-10-18T06:00:00Z</fcst_time_to>
<change_indicator>BECMG</change_indicator>
<time_becoming>2017-10-17T09:00:00Z</time_becoming>
<wind_dir_degrees>220</wind_dir_degrees>
<wind_speed_kt>10</wind_speed_kt>
<visibility_statute_mi>6.21</visibility_statute_mi>
<wx_string>NSW</wx_string>
<sky_condition sky_cover="NSC" />
</forecast>
</TAF>
<TAF>
<raw_text>TAF EPGD 162330Z 1700/1724 24006KT 7000 SCT012 TEMPO 1700/1708 BKN005 PROB40 1702/1707 1000 BR OVC002</raw_text>
<station_id>EPGD</station_id>
<issue_time>2017-10-16T23:30:00Z</issue_time>
<bulletin_time>2017-10-16T23:00:00Z</bulletin_time>
<valid_time_from>2017-10-17T00:00:00Z</valid_time_from>
<valid_time_to>2017-10-18T00:00:00Z</valid_time_to>
<latitude>54.37</latitude>
<longitude>18.47</longitude>
<elevation_m>138.0</elevation_m>
<forecast>
<fcst_time_from>2017-10-17T00:00:00Z</fcst_time_from>
<fcst_time_to>2017-10-17T08:00:00Z</fcst_time_to>
<change_indicator>TEMPO</change_indicator>
<sky_condition sky_cover="BKN" cloud_base_ft_agl="500" />
</forecast>
<forecast>
<fcst_time_from>2017-10-17T00:00:00Z</fcst_time_from>
<fcst_time_to>2017-10-18T00:00:00Z</fcst_time_to>
<wind_dir_degrees>240</wind_dir_degrees>
<wind_speed_kt>6</wind_speed_kt>
<visibility_statute_mi>4.35</visibility_statute_mi>
<sky_condition sky_cover="SCT" cloud_base_ft_agl="1200" />
</forecast>
<forecast>
<fcst_time_from>2017-10-17T02:00:00Z</fcst_time_from>
<fcst_time_to>2017-10-17T07:00:00Z</fcst_time_to>
<change_indicator>PROB</change_indicator>
<probability>40</probability>
<visibility_statute_mi>0.62</visibility_statute_mi>
<wx_string>BR</wx_string>
<sky_condition sky_cover="OVC" cloud_base_ft_agl="200" />
</forecast>
</TAF>
<TAF>
<raw_text>TAF EPGD 161730Z 1618/1718 24006KT CAVOK BECMG 1618/1620 BKN013 TEMPO 1621/1708 BKN005 PROB40 1700/1707 2000 BR OVC002 BECMG 1709/1711 SCT030</raw_text>
<station_id>EPGD</station_id>
<issue_time>2017-10-16T17:30:00Z</issue_time>
<bulletin_time>2017-10-16T17:00:00Z</bulletin_time>
<valid_time_from>2017-10-16T18:00:00Z</valid_time_from>
<valid_time_to>2017-10-17T18:00:00Z</valid_time_to>
<latitude>54.37</latitude>
<longitude>18.47</longitude>
<elevation_m>138.0</elevation_m>
<forecast>
<fcst_time_from>2017-10-16T18:00:00Z</fcst_time_from>
<fcst_time_to>2017-10-17T18:00:00Z</fcst_time_to>
<wind_dir_degrees>240</wind_dir_degrees>
<wind_speed_kt>6</wind_speed_kt>
<visibility_statute_mi>6.21</visibility_statute_mi>
<wx_string>NSW</wx_string>
<sky_condition sky_cover="NSC" />
</forecast>
<forecast>
<fcst_time_from>2017-10-16T18:00:00Z</fcst_time_from>
<fcst_time_to>2017-10-17T09:00:00Z</fcst_time_to>
<change_indicator>BECMG</change_indicator>
<time_becoming>2017-10-16T20:00:00Z</time_becoming>
<wind_dir_degrees>240</wind_dir_degrees>
<wind_speed_kt>6</wind_speed_kt>
<visibility_statute_mi>6.21</visibility_statute_mi>
<wx_string>NSW</wx_string>
<sky_condition sky_cover="BKN" cloud_base_ft_agl="1300" />
</forecast>
<forecast>
<fcst_time_from>2017-10-16T21:00:00Z</fcst_time_from>
<fcst_time_to>2017-10-17T08:00:00Z</fcst_time_to>
<change_indicator>TEMPO</change_indicator>
<sky_condition sky_cover="BKN" cloud_base_ft_agl="500" />
</forecast>
<forecast>
<fcst_time_from>2017-10-17T00:00:00Z</fcst_time_from>
<fcst_time_to>2017-10-17T07:00:00Z</fcst_time_to>
<change_indicator>PROB</change_indicator>
<probability>40</probability>
<visibility_statute_mi>1.24</visibility_statute_mi>
<wx_string>BR</wx_string>
<sky_condition sky_cover="OVC" cloud_base_ft_agl="200" />
</forecast>
<forecast>
<fcst_time_from>2017-10-17T09:00:00Z</fcst_time_from>
<fcst_time_to>2017-10-17T18:00:00Z</fcst_time_to>
<change_indicator>BECMG</change_indicator>
<time_becoming>2017-10-17T11:00:00Z</time_becoming>
<wind_dir_degrees>240</wind_dir_degrees>
<wind_speed_kt>6</wind_speed_kt>
<visibility_statute_mi>6.21</visibility_statute_mi>
<wx_string>NSW</wx_string>
<sky_condition sky_cover="SCT" cloud_base_ft_agl="3000" />
</forecast>
</TAF>
</data>
</response>
我POJO類看起來是這樣的:
@XmlRootElement(name = "response")
public class Response {
@XmlElement private List<Taf> data; // I don't need any other contents of this element
public List<Taf> getData() {
return data;
}
public void setData(List<Taf> data) {
this.data = data;
}
}
@XmlRootElement(name = "TAF")
public class Taf {
@XmlElement(name = "raw_text") private String raw_text;
@XmlElement(name = "station_id") private String station_id; // ICAO
@XmlElement(name = "issue_time") private Date issue_time;
@XmlElement(name = "bulletin_time") private Date bulletin_time;
@XmlElement(name = "valid_time_from") private Date valid_time_from;
@XmlElement(name = "valid_time_to") private Date valid_time_to;
@XmlElement(name = "remarks") private String remarks;
@XmlElement(name = "latitude") private Double latitude;
@XmlElement(name = "longitude") private Double longitude;
@XmlElement(name = "elevation_m") private Double elevation_m;
@XmlElement(name = "forecast", type = Forecast.class) private List<Forecast> forecast;
// getters and setters
}
@XmlRootElement(name = "forecast")
public class Forecast {
@XmlElement(name = "fcst_time_from") private Date fcst_time_from;
@XmlElement(name = "fcst_time_to") private Date fcst_time_to;
@XmlElement(name = "wind_dir_degrees") private Integer wind_dir_degrees;
@XmlElement(name = "wind_speed_kt") private Integer wind_speed_kt;
@XmlElement(name = "visibility_statute_mi") private Double visibility_statute_mi;
@XmlElement(name = "wx_string") private String wx_string;
@XmlElement(name = "sky_condition", type = SkyCondition.class) private List<SkyCondition> sky_condition;
// getters and setters
}
@XmlRootElement(name = "sky_condition")
public class SkyCondition {
@XmlAttribute(name = "sky_cover") private String sky_cover;
@XmlAttribute(name = "cloud_base_ft_agl") private Integer cloud_base_ft_agl;
// getters and setters
}
現在我的服務有一個簡單的方法:
public List<Taf> getTafsForICAO(String icao) {
RestTemplate restTemplate = new RestTemplate();
Response resp = restTemplate.getForObject(tafUrl+icao, Response.class);
return resp.getData();
}
如果我忽略嵌套的forecast
元素,則所有內容都正確解析。但我需要這些嵌套元素,如果我運行一切,因爲它是,我得到以下異常:
Failed to read HTTP message:
org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error:
Can not construct instance of airports.models.taf.Forecast:
no String-argument constructor/factory method to deserialize from String value ('2017-10-17T12:00:00Z'); nested exception is
com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of airports.models.taf.Forecast: no String-argument constructor/factory method to deserialize from String value ('2017-10-17T12:00:00Z')
at [Source: [email protected]; line: 21, column: 45] (through reference chain: airports.models.taf.Response["data"]->java.util.ArrayList[0]->airports.models.taf.Taf["forecast"]->java.util.ArrayList[0])
它看起來像解析器看到forecast
第一個子元素,這是fcst_time_from
了它的內容,並試圖將日期反序列化爲Forecast
對象。我不知道爲什麼。也許我錯過了一些簡單的東西?預先感謝您的幫助。
UPDATE
我有點接近這個問題。嵌套的TAF
元素在response
元素中被正確解析,因爲它們被包裝在data
元素中。不幸的是,TAF
內部沒有包含forecast
標籤列表的包裝元素。我爲Forecast
類創建了一個帶String參數的構造函數,現在它將嵌入元素(fcst_time_from,fcst_time_to等)解析爲Forcast
對象。有沒有辦法來聲明這個內部列表沒有包裝元素?
更新2
一些測試後,我想通了problewm是嚴格把解析的元素展開列表。我不知道爲什麼,但如果我宣佈我的Result
類這樣的,而不是顯示更高的聲明:
@XmlRootElement(name = "response")
public class Response {
@XmlElementWrapper(name = "data")
@XmlElement(name = "TAF")
private List<Taf> tafs;
public List<Taf> getTafs() {
return tafs;
}
public void setTafs(List<Taf> tafs) {
this.tafs = tafs;
}
}
它不工作。沒有TAF元素被解析。這似乎是解析器迫使所有列表被包裝。不幸的是,我在REST輸出中打開了forecast
列表。我該如何處理這個問題?我看到@Element(inline = true)
註釋的參數,但@XmlElement
沒有這樣的事情。我可以以某種方式強制RestTemplate本身的解包列表?
請先修復主要問題,然後我們可以看到......主要問題是:您的RestTemplate無法將'2017-10-17T12:00:00Z'解析/反序列化爲'java.util。日期'!有關解決方案,請參閱:https://stackoverflow.com/q/21355450/592355('ObjectMapper.setDateFormat()'!) – xerx593
@ xerx593不,不是。它將'2017-10-17T12:00:00Z'解析爲'java.utill.Date',沒有問題。當我註釋列表預測Taf對象正確解析(並且它們包含日期字段)。此錯誤表示它嘗試將此日期字符串反序列化爲Forecast對象。 –
Yaerius