前言
在現(xiàn)如今的Android開發(fā)中,尤其是互聯(lián)網(wǎng)軟件,客戶端與服務(wù)器端的交互可謂是家常便飯,而在Android端,通過訪問接口接收到服務(wù)器端返回的Json格式的數(shù)據(jù)的情形幾乎百分之九十的開發(fā)者都會遇到,這篇文章就對一些基本的到復(fù)雜的Json數(shù)據(jù)的解析進(jìn)行一個全面的分析,從實戰(zhàn)出發(fā),至少希望你看完,能知道怎么做。
一、Json和Gson
Json是當(dāng)前業(yè)內(nèi)使用最為廣泛的一種數(shù)據(jù)傳輸格式,大多數(shù)服務(wù)器端的API使用JSON作為數(shù)據(jù)的返回格式,也就是大家知道的,采用鍵值對的方式來記錄數(shù)據(jù)。
Gson是Google提供的用來在Java對象和JSON數(shù)據(jù)之間進(jìn)行映射的Java類庫??梢詫⒁粋€Json字符轉(zhuǎn)成一個Java對象,或者將一個Java轉(zhuǎn)化為Json字符串。
其實一句話來說,json是一種數(shù)據(jù)格式,便于數(shù)據(jù)傳輸、存儲、交換,而gson是一種組件庫,可以把java對象數(shù)據(jù)轉(zhuǎn)換成json數(shù)據(jù)格式。
二、常規(guī)的Json數(shù)據(jù)解析
使用Gson對Json數(shù)據(jù)進(jìn)行解析,其實只要根據(jù)Json數(shù)據(jù)設(shè)計好你的實體類,就沒問題了,從實戰(zhàn)出發(fā),看Json:
{ "resultcode":"200",
"reason":"successed!",
"result":{
"base":{
"temp":"24",
"wind_direction":"東北風(fēng)",
"wind_strength":"2級",
"humidity":"28%",
"time":"17:38"
},
"today":{
"temperature":"15℃~26℃",
"weather":"多云轉(zhuǎn)晴",
"wind":"東北風(fēng)微風(fēng)",
"week":"星期日",
},
},
"error_code":0
}
Json數(shù)據(jù)的層次都很清晰,鍵值對的映射也一目了然,上面是一個查詢天氣的接口返回的數(shù)據(jù),從外到內(nèi),你可以理解為有resultcode,reason,result,error_code四個類對象,而reslut里面還包含base和today兩個類對象,以此類推。那么接下來就根據(jù)這個數(shù)據(jù)格式在你的工程中創(chuàng)建對應(yīng)的實體類,當(dāng)然你可以使用Android Studio的GsonFormat插件偷一偷懶:
安裝此插件后,新建一個實體類,如新建一個WeatherEntity類,然后在類文件中調(diào)用菜單使用該插件:
然后把你需要解析的Json數(shù)據(jù)復(fù)制粘貼到彈窗中,點OK就可以了,是不是很傻瓜式呢:
之后你的實體類就創(chuàng)建好了:
public class WeatherEntity {
/**
* resultcode : 200
* reason : successed!
* result : {"base":{"temp":"24","wind_direction":"東北風(fēng)","wind_strength":"2級","humidity":"28%","time":"17:38"},"today":{"temperature":"15℃~26℃","weather":"多云轉(zhuǎn)晴","wind":"東北風(fēng)微風(fēng)","week":"星期日"}}
* error_code : 0
*/
private String resultcode;
private String reason;
private ResultBean result;
private int error_code;
public String getResultcode() {
return resultcode;
}
public void setResultcode(String resultcode) {
this.resultcode = resultcode;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
public ResultBean getResult() {
return result;
}
public void setResult(ResultBean result) {
this.result = result;
}
public int getError_code() {
return error_code;
}
public void setError_code(int error_code) {
this.error_code = error_code;
}
public static class ResultBean {
/**
* base: {"temp":"24","wind_direction":"東北風(fēng)","wind_strength":"2級","humidity":"28%","time":"17:38"}
* today : {"temperature":"15℃~26℃","weather":"多云轉(zhuǎn)晴","wind":"東北風(fēng)微風(fēng)","week":"星期日"}
*/
private BaseBean base;
private TodayBean today;
public BaseBean getBase() {
return base;
}
public void setBase(BaseBean base) {
this.base= base;
}
public TodayBean getToday() {
return today;
}
public void setToday(TodayBean today) {
this.today = today;
}
public static class BaseBean {
/**
* temp : 24
* wind_direction : 東北風(fēng)
* wind_strength : 2級
* humidity : 28%
* time : 17:38
*/
private String temp;
private String wind_direction;
private String wind_strength;
private String humidity;
private String time;
public String getTemp() {
return temp;
}
public void setTemp(String temp) {
this.temp = temp;
}
public String getWind_direction() {
return wind_direction;
}
public void setWind_direction(String wind_direction) {
this.wind_direction = wind_direction;
}
public String getWind_strength() {
return wind_strength;
}
public void setWind_strength(String wind_strength) {
this.wind_strength = wind_strength;
}
public String getHumidity() {
return humidity;
}
public void setHumidity(String humidity) {
this.humidity = humidity;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
}
public static class TodayBean {
/**
* temperature : 15℃~26℃
* weather : 多云轉(zhuǎn)晴
* wind : 東北風(fēng)微風(fēng)
* week : 星期日
*/
private String temperature;
private String weather;
private String wind;
private String week;
public String getTemperature() {
return temperature;
}
public void setTemperature(String temperature) {
this.temperature = temperature;
}
public String getWeather() {
return weather;
}
public void setWeather(String weather) {
this.weather = weather;
}
public String getWind() {
return wind;
}
public void setWind(String wind) {
this.wind = wind;
}
public String getWeek() {
return week;
}
public void setWeek(String week) {
this.week = week;
}
}
}
}
需要提醒各位的是,實體類的類名你可以按自己心情定,但是對象名一定要與Json數(shù)據(jù)中的key一一對應(yīng),如上面的“private ResultBean result”里的"result",就不能隨意取名。
然后在網(wǎng)絡(luò)請求中直接使用如下語句就可以將Json數(shù)據(jù)轉(zhuǎn)化到你的實體類對象了:
Gson gson = new Gson();
WeatherEntity weatherEntity = gson.fromJson(result, WeatherEntity .class);//result就是服務(wù)器返回的Json字符串
三、解析key為動態(tài)未知字段的Json數(shù)據(jù)
上面是一個很簡單很標(biāo)準(zhǔn)的Json數(shù)據(jù),每一個key指向一個value,key不會發(fā)生變化,不同的只是其中的value,但是如果該Json數(shù)據(jù)加上以下的內(nèi)容,你還會不會正常的解析出來呢:
{ "resultcode":"200",
"reason":"successed!",
"result":{
"base":{
"temp":"24",
"wind_direction":"東北風(fēng)",
"wind_strength":"2級",
"humidity":"28%",
"time":"17:38"
},
"today":{
"temperature":"15℃~26℃",
"weather":"多云轉(zhuǎn)晴",
"wind":"東北風(fēng)微風(fēng)",
"week":"星期日",
},
"future":{
"day_20181011":{"temperature":"15℃~26℃","weather":"多云轉(zhuǎn)晴"},
"day_20181012":{"temperature":"16℃~27℃","weather":"晴轉(zhuǎn)多云"},
"day_20181013":{"temperature":"16℃~26℃","weather":"多云轉(zhuǎn)晴"},
}
},
"error_code":0
}
如上述Json數(shù)據(jù),在天氣數(shù)據(jù)中增加了未來幾天的天氣,如果你依然按照之前的方法,對該數(shù)據(jù)進(jìn)行類實體化,那么可想而知你的Future類里會出現(xiàn)以下三個類:day_20181011類,day_20181011類和day_20181011類,因為Gson是高度封裝的,你的key是什么,他就會根據(jù)你的key生成對應(yīng)的類,用這種傳統(tǒng)的方法無法對這種key是動態(tài)的,未知的情況進(jìn)行處理,像天氣這種數(shù)據(jù),每一天的日期都不同,采用這種動態(tài)值作為key的時候,我們該如何解析呢?
答案是,在Gson中,我們可以用Map的形式來對這種動態(tài)key的Json數(shù)據(jù)進(jìn)行解析,例如上面的Future類,里面的key是動態(tài)可變的日期,值是一個固定的天氣類數(shù)據(jù)(溫度和天氣類型),那么我們可以如下表示該字段:
private Map<String,FutureWeather> future;//String就對應(yīng)著動態(tài)變化的day_20181011、day_20181012...
public static class FutureWeather{
private String temperature;
private String weather;
.........//get set 方法...
}
明白了嗎,當(dāng)然對應(yīng)的該Map對象的屬性名一定要為"future",與Json數(shù)據(jù)中的字段對應(yīng),這一點一定要注意,所以上述Json完整的實體類應(yīng)為(此處略去set/get方法):
public class WeatherEntity {
/**
* resultcode : 200
* reason : successed!
* result : {"base":{"temp":"24","wind_direction":"東北風(fēng)","wind_strength":"2級","humidity":"28%","time":"17:38"},"today":{"temperature":"15℃~26℃","weather":"多云轉(zhuǎn)晴","wind":"東北風(fēng)微風(fēng)","week":"星期日"}}
* error_code : 0
*/
private String resultcode;
private String reason;
private ResultBean result;
private int error_code;
public static class ResultBean {
/**
* base: {"temp":"24","wind_direction":"東北風(fēng)","wind_strength":"2級","humidity":"28%","time":"17:38"}
* today : {"temperature":"15℃~26℃","weather":"多云轉(zhuǎn)晴","wind":"東北風(fēng)微風(fēng)","week":"星期日"}
*/
private BaseBean base;
private TodayBean today;
private Map<String,FutureWeather> future;
public static class FutureWeather{
private String temperature;
private String weather;
}
public static class BaseBean {
/**
* temp : 24
* wind_direction : 東北風(fēng)
* wind_strength : 2級
* humidity : 28%
* time : 17:38
*/
private String temp;
private String wind_direction;
private String wind_strength;
private String humidity;
private String time;
}
public static class TodayBean {
/**
* temperature : 15℃~26℃
* weather : 多云轉(zhuǎn)晴
* wind : 東北風(fēng)微風(fēng)
* week : 星期日
*/
private String temperature;
private String weather;
private String wind;
private String week;
}
}
}
接下來你就可以使用同樣的方法把Json數(shù)據(jù)轉(zhuǎn)化為實體類了。
使用Gson解析Json數(shù)據(jù)的方法今天暫且寫這么多,大家可能已經(jīng)遇到了更為復(fù)雜的數(shù)據(jù),但是萬變不離其宗,也歡迎大家留言討論~
祝大家敲的刺激,敲的愉快(滑稽)~