1. 程式人生 > >Android——Json資料全解析

Android——Json資料全解析

前言

在現如今的Android開發中,尤其是網際網路軟體,客戶端與伺服器端的互動可謂是家常便飯,而在Android端,通過訪問介面接收到伺服器端返回的Json格式的資料的情形幾乎百分之九十的開發者都會遇到,這篇文章就對一些基本的到複雜的Json資料的解析進行一個全面的分析,從實戰出發,至少希望你看完,能知道怎麼做。

一、Json和Gson

Json是當前業內使用最為廣泛的一種資料傳輸格式,大多數伺服器端的API使用JSON作為資料的返回格式,也就是大家知道的,採用鍵值對的方式來記錄資料。 Gson是Google提供的用來在Java物件和JSON資料之間進行對映的Java類庫。可以將一個Json字元轉成一個Java物件,或者將一個Java轉化為Json字串。 其實一句話來說,json是一種資料格式,便於資料傳輸、儲存、交換,而gson是一種元件庫,可以把java物件資料轉換成json資料格式。

二、常規的Json資料解析

使用Gson對Json資料進行解析,其實只要根據Json資料設計好你的實體類,就沒問題了,從實戰出發,看Json:

{ "resultcode":"200",
  "reason":"successed!",
    "result":{
            "sk":{
                 "temp":"24",
                 "wind_direction":"東北風",
                 "wind_strength":"2級",
                 "humidity":"28%",
                 "time":"17:38"
                  },
         "today":{
                 "temperature":"15℃~26℃",
                 "weather":"多雲轉晴",
                 "wind":"東北風微風",
                 "week":"星期日",
                 },
              },
    "error_code":0
}

Json資料的層次都很清晰,鍵值對的對映也一目瞭然,上面是一個查詢天氣的介面返回的資料,從外到內,你可以理解為有resultcode,reason,result,error_code四個類物件,而reslut裡面還包含sk和today兩個類物件,以此類推。那麼接下來就根據這個資料格式在你的工程中建立對應的實體類,當然你可以使用Android Studio的GsonFormat外掛偷一偷懶: 安裝此外掛後,新建一個實體類,如新建一個WeatherEntity類,然後在類檔案中呼叫選單使用該外掛: 然後把你需要解析的Json資料複製貼上到彈窗中,點OK就可以了,是不是很傻瓜式呢: 之後你的實體類就建立好了:

public class WeatherEntity {

    /**
     * resultcode : 200
     * reason : successed!
     * result : {"sk":{"temp":"24","wind_direction":"東北風","wind_strength":"2級","humidity":"28%","time":"17:38"},"today":{"temperature":"15℃~26℃","weather":"多雲轉晴","wind":"東北風微風","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 {
        /**
         * sk : {"temp":"24","wind_direction":"東北風","wind_strength":"2級","humidity":"28%","time":"17:38"}
         * today : {"temperature":"15℃~26℃","weather":"多雲轉晴","wind":"東北風微風","week":"星期日"}
         */

        private SkBean sk;
        private TodayBean today;

        public SkBean getSk() {
            return sk;
        }

        public void setSk(SkBean sk) {
            this.sk = sk;
        }

        public TodayBean getToday() {
            return today;
        }

        public void setToday(TodayBean today) {
            this.today = today;
        }

        public static class SkBean {
            /**
             * temp : 24
             * wind_direction : 東北風
             * 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 : 多雲轉晴
             * wind : 東北風微風
             * 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資料中的key一一對應,如上面的“private ResultBean result”裡的"result",就不能隨意取名。 然後在網路請求中直接使用如下語句就可以將Json資料轉化到你的實體類物件了:

Gson gson = new Gson();
WeatherEntity weatherEntity = gson.fromJson(result, WeatherEntity .class);//result就是伺服器返回的Json字串

三、解析key為動態未知欄位的Json資料

上面是一個很簡單很標準的Json資料,每一個key指向一個value,key不會發生變化,不同的只是其中的value,但是如果該Json資料加上以下的內容,你還會不會正常的解析出來呢:

{ "resultcode":"200",
  "reason":"successed!",
    "result":{
            "sk":{
                 "temp":"24",
                 "wind_direction":"東北風",
                 "wind_strength":"2級",
                 "humidity":"28%",
                 "time":"17:38"
                  },
         "today":{
                 "temperature":"15℃~26℃",
                 "weather":"多雲轉晴",
                 "wind":"東北風微風",
                 "week":"星期日",
                 },
         "future":{
                 "day_20181011":{"temperature":"15℃~26℃","weather":"多雲轉晴"},
                 "day_20181012":{"temperature":"16℃~27℃","weather":"晴轉多雲"},
                 "day_20181013":{"temperature":"16℃~26℃","weather":"多雲轉晴"},
                 }
            },
    "error_code":0
}

如上述Json資料,在天氣資料中增加了未來幾天的天氣,如果你依然按照之前的方法,對該資料進行類實體化,那麼可想而知你的Future類裡會出現以下三個類:day_20181011類,day_20181011類和day_20181011類,因為Gson是高度封裝的,你的key是什麼,他就會根據你的key生成對應的類,用這種傳統的方法無法對這種key是動態的,未知的情況進行處理,像天氣這種資料,每一天的日期都不同,採用這種動態值作為key的時候,我們該如何解析呢? 答案是,在Gson中,我們可以用Map的形式來對這種動態key的Json資料進行解析,例如上面的Future類,裡面的key是動態可變的日期,值是一個固定的天氣類資料(溫度和天氣型別),那麼我們可以如下表示該欄位:

private Map<String,FutureWeather> future;//String就對應著動態變化的day_20181011、day_20181012...
public static class FutureWeather{
	private String temperature;
	private String weather;
	.........//get set 方法...
}

明白了嗎,當然對應的該Map物件的屬性名一定要為"future",與Json資料中的欄位對應,這一點一定要注意,所以上述Json完整的實體類應為(此處略去set/get方法):

public class WeatherEntity {

    /**
     * resultcode : 200
     * reason : successed!
     * result : {"sk":{"temp":"24","wind_direction":"東北風","wind_strength":"2級","humidity":"28%","time":"17:38"},"today":{"temperature":"15℃~26℃","weather":"多雲轉晴","wind":"東北風微風","week":"星期日"}}
     * error_code : 0
     */

    private String resultcode;
    private String reason;
    private ResultBean result;
    private int error_code;
    public static class ResultBean {
        /**
         * sk : {"temp":"24","wind_direction":"東北風","wind_strength":"2級","humidity":"28%","time":"17:38"}
         * today : {"temperature":"15℃~26℃","weather":"多雲轉晴","wind":"東北風微風","week":"星期日"}
         */

        private SkBean sk;
        private TodayBean today;
        private Map<String,FutureWeather> future;
		public static class FutureWeather{
				private String temperature;
				private String weather;
		 }
        public static class SkBean {
            /**
             * temp : 24
             * wind_direction : 東北風
             * 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 : 多雲轉晴
             * wind : 東北風微風
             * week : 星期日
             */

            private String temperature;
            private String weather;
            private String wind;
            private String week;
        }
    }
}

接下來你就可以使用同樣的方法把Json資料轉化為實體類了。 使用Gson解析Json資料的方法今天暫且寫這麼多,大家可能已經遇到了更為複雜的資料,但是萬變不離其宗,也歡迎大家留言討論~ 祝大家敲的刺激,敲的愉快(滑稽)~