Android——Json數(shù)據(jù)全解析

前言

在現(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插件偷一偷懶:


image

安裝此插件后,新建一個實體類,如新建一個WeatherEntity類,然后在類文件中調(diào)用菜單使用該插件:


image

然后把你需要解析的Json數(shù)據(jù)復(fù)制粘貼到彈窗中,點OK就可以了,是不是很傻瓜式呢:
image

之后你的實體類就創(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ù),但是萬變不離其宗,也歡迎大家留言討論~
祝大家敲的刺激,敲的愉快(滑稽)~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容