JSON格式数据学习和在Android中用JSONobject和Gson解析网络数据

本人刚入门,有错误请评论指出

一、Json相关知识点

  1. 什么是Json?

    • Json是一种存储数据信息的语法格式
    • Json类似于XML,但是比XML更小、更快、更易解析
  2. Json的语法规则

    • 数据保存为“键/值”对的格式
    • 数据由逗号分隔
    • 花括号保存的是对象
    • 方括号保存的是数据
  3. Json的值可以是以下格式:

    • 数字(整型和浮点型)
    • 字符串(在双引号中)
    • 逻辑值(boolean)
    • 数组(在方括号中)
    • 对象(在花括号中)
    • null
  4. Json的例子“

    {
    "employees": [
    { "firstName":"John" , "lastName":"Doe" },
    { "firstName":"Anna" , "lastName":"Smith" },
    { "firstName":"Peter" , "lastName":"Jones" }
    ]
    }
    

    最外层花括号为一个对象Object,里层有一个键为”employees“,对应的值为一个数组,数组中又包含三个对象Object,分别用来描述每个员工的姓名,包含三个字符串类型的键值对。


二、如何解析Json格式的数据

  1. 返回Json格式的API:http://guolin.tech/api/weather?cityid=CN101280601&key=077b0519028e413ebfda3fad3d142dd4

  2. 顺便介绍一个解析和格式化Json的在线网站,挺好用的

    https://www.json.cn/

  3. 此API返回的数据如下:

    {
        "HeWeather":[
            {
                "basic":{
                    "cid":"CN101280601",
                    "location":"深圳",
                    "parent_city":"深圳",
                    "admin_area":"广东",
                    "cnty":"中国",
                    "lat":"36.67580795",
                    "lon":"117.00092316",
                    "tz":"+8.00",
                    "city":"深圳",
                    "id":"CN101280601",
                    "update":{
                        "loc":"2019-09-08 10:29",
                        "utc":"2019-09-08 02:29"
                    }
                },
                "update":{
                    "loc":"2019-09-08 10:29",
                    "utc":"2019-09-08 02:29"
                },
                "status":"ok",
                "now":{
                    "cloud":"10",
                    "cond_code":"104",
                    "cond_txt":"阴",
                    "fl":"8",
                    "hum":"60",
                    "pcpn":"0.0",
                    "pres":"1015",
                    "tmp":"12",
                    "vis":"16",
                    "wind_deg":"261",
                    "wind_dir":"西风",
                    "wind_sc":"3",
                    "wind_spd":"17",
                    "cond":{
                        "code":"104",
                        "txt":"阴"
                    }
                },
                "daily_forecast":[
                    {
                        "date":"2019-09-09",
                        "cond":{
                            "txt_d":"阴"
                        },
                        "tmp":{
                            "max":"17",
                            "min":"6"
                        }
                    },
                    {
                        "date":"2019-09-10",
                        "cond":{
                            "txt_d":"晴"
                        },
                        "tmp":{
                            "max":"14",
                            "min":"3"
                        }
                    },
                    {
                        "date":"2019-09-11",
                        "cond":{
                            "txt_d":"晴"
                        },
                        "tmp":{
                            "max":"15",
                            "min":"6"
                        }
                    },
                    {
                        "date":"2019-09-12",
                        "cond":{
                            "txt_d":"多云"
                        },
                        "tmp":{
                            "max":"20",
                            "min":"6"
                        }
                    },
                    {
                        "date":"2019-09-13",
                        "cond":{
                            "txt_d":"晴"
                        },
                        "tmp":{
                            "max":"18",
                            "min":"5"
                        }
                    },
                    {
                        "date":"2019-09-14",
                        "cond":{
                            "txt_d":"多云"
                        },
                        "tmp":{
                            "max":"19",
                            "min":"7"
                        }
                    }
                ],
                "aqi":{
                    "city":{
                        "aqi":"112",
                        "pm25":"60",
                        "qlty":"轻度污染"
                    }
                },
                "suggestion":{
                    "comf":{
                        "type":"comf",
                        "brf":"舒适",
                        "txt":"白天不太热也不太冷,风力不大,相信您在这样的天气条件下,应会感到比较清爽和舒适。"
                    },
                    "sport":{
                        "type":"sport",
                        "brf":"较适宜",
                        "txt":"阴天,较适宜进行各种户内外运动。"
                    },
                    "cw":{
                        "type":"cw",
                        "brf":"较适宜",
                        "txt":"较适宜洗车,未来一天无雨,风力较小,擦洗一新的汽车至少能保持一天。"
                    }
                },
                "msg":"所有天气数据均为模拟数据,仅用作学习目的使用,请勿当作真实的天气预报软件来使用。"
            }
        ]
    }
    

    其实无论多么复杂的Json数据,都是由数组和对象组成的,所以解析的时候也重点关注对象和数组的层级结构就好。

  4. 在Android中利用JsonObject解析数据

    1. Android中请求网络API我使用的是OkHttp的开源库,可以去GitHub上搜索

    2. 请求网络数据的代码

      package com.example.kh.okhttpjsondemo;
      
      import java.io.IOException;
      import okhttp3.OkHttpClient;
      import okhttp3.Request;
      import okhttp3.Response;
      /*
       * @author: KangHui
       * @date: 2019/9/7 23:20
       *请求网络数据,返回的就是Json形式的字符串
       */
      public class GetOkHttpResponse {
          public static OkHttpClient client = new OkHttpClient();
      
          public static String run(String url) throws IOException {
              Request request = new Request.Builder()
                      .url(url)
                      .build();
      
              try (Response response = client.newCall(request).execute()) {
                  return response.body().string();
              }
          }
      }
      

    3. 解析网络请求返回的Json数据

      package com.example.kh.okhttpjsondemo;
      
      import androidx.appcompat.app.AppCompatActivity;
      
      import android.os.Bundle;
      import android.util.Log;
      import android.widget.TextView;
      
      import org.json.JSONArray;
      import org.json.JSONException;
      import org.json.JSONObject;
      
      import java.io.IOException;
      
      public class MainActivity extends AppCompatActivity {
          private static final String TAG = "MainActivity";
          private static final String URL = "http://guolin.tech/api/weather?cityid=CN101280601&key=077b0519028e413ebfda3fad3d142dd4";
          private String responseString;
          private TextView mTextView;
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
              mTextView = (TextView) findViewById(R.id.text_view);
              /*Android4.0之后不能在主线程中进行网络请求*/
              new Thread(new Runnable() {
                  @Override
                  public void run() {
                      try {
                          responseString = GetOkHttpResponse.run(URL);
                          Log.d(TAG, "onCreate: "+responseString);
                          JSONObject jsonObject = new JSONObject(responseString);//最外层对象
                          JSONArray heWeather = jsonObject.getJSONArray("HeWeather");//HeWeather数组
                          JSONObject jsonObject1 = heWeather.getJSONObject(0);//数组中的第一个对象
                          JSONObject basic = jsonObject1.getJSONObject("basic");//第一个对象中又包含一个basic对象
                          String location = basic.getString("location");//basic对象中的字符串类型location
                          String status = jsonObject1.getString("status");//第一个对象中的字符串status
                          Log.d(TAG, "run: "+location);
                          Log.d(TAG, "run: "+status);
                      } catch (IOException e) {
                          e.printStackTrace();
                      } catch (JSONException e) {
                          e.printStackTrace();
                      }
                  }
              }).start();
          }
      }
      
      

      可以看到利用JsonObject解析数据就是一层一层的剥开数据,然后取出来就行。这种方式对于简单的Json数据格式还不错,但是对于比较复杂的Json数据解析就比较麻烦了。

  5. 在Android中利用Gson来解析

    1. Gson

      https://github.com/google/gson Gson是一个可以直接将Json数据和java对象相互转换的java库

    2. 利用Gson解析首先要按照待解析的json数据格式写出相应的数据类

    3. 观察发现上面的json数据中最外层的对象中只包含一个HeWeather的数组,而此数组中仅包含一个对象;

      因此我们可以创建一个类表示这个数组中的对象;然后这个类中又包含一个basic对象,一个update对象,一个status的字符串,以及一个daily_forcast的列表来表示json中的对应数组。(简单起见就先解析这些数据)

      数据文件目录:
      在这里插入图片描述

package com.example.kh.okhttpjsondemo.data;

import com.google.gson.annotations.SerializedName;

public class Basic {
    public String cid;
    public String location;
    public String city;
    @SerializedName("cnty")
    public String country;  //这个名字与json数据中的名词不一样
}

package com.example.kh.okhttpjsondemo.data;

public class Update {
    public String loc;
    public String utc;
}
package com.example.kh.okhttpjsondemo.data;

import com.google.gson.annotations.SerializedName;

public class Forecast {
    @SerializedName("date")
    public String forcaseDate;
    public Cond cond;   //创建cond对象

    //json中此处又是一个对象
    public class Cond{
        public String txt_d;
    }
}
package com.example.kh.okhttpjsondemo.data;

import com.google.gson.annotations.SerializedName;

import java.util.List;

public class Weather {
    public Basic basic;
    public Update update;
    public String status;
    @SerializedName("daily_forecast")
    public List<Forecast> forecastList;
}

注:当自定义的类中变量名与json中不一样时需要使用注解SerializedName来重命名

  1. 利用网络请求返回的json字符串解析

    package com.example.kh.okhttpjsondemo;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.os.Bundle;
    import android.util.Log;
    import android.widget.TextView;
    
    import com.example.kh.okhttpjsondemo.data.Weather;
    import com.google.gson.Gson;
    import com.google.gson.JsonArray;
    import com.google.gson.JsonObject;
    
    import org.json.JSONArray;
    import org.json.JSONException;
    import org.json.JSONObject;
    
    import java.io.IOException;
    
    public class MainActivity extends AppCompatActivity {
        private static final String TAG = "MainActivity";
        private static final String URL = "http://guolin.tech/api/weather?cityid=CN101280601&key=077b0519028e413ebfda3fad3d142dd4";
        private String responseString;
        private TextView mTextView;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mTextView = (TextView) findViewById(R.id.text_view);
            /*Android4.0之后不能在主线程中进行网络请求*/
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        responseString = GetOkHttpResponse.run(URL);
                        Log.d(TAG, "onCreate: "+responseString);
                        //注意此处Gson库中有JsonObject和Android自带的JSONObject的区别
                        JSONObject jsonObject = new JSONObject(responseString);
                        JSONArray heWeather = jsonObject.getJSONArray("HeWeather");
                        JSONObject weather = heWeather.getJSONObject(0);
                        Weather resultWeather = new Gson().fromJson(weather.toString(),Weather.class);
                        Log.d(TAG, "run: "+resultWeather.status);
                        Log.d(TAG, "run: "+resultWeather.basic.city);
                        Log.d(TAG, "run: "+resultWeather.forecastList.get(1).forcaseDate);
    
                    } catch (JSONException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }
    
    

在这里插入图片描述

gson解析就是将自己创建的对象的格式和json数据的格式写成一样的,然后就可以对应到对象中了。这对于复杂数据的解析要方便一些。需要注意的就是当自己定义的类中的变量名与json数据中的变量名不一样时一定要使用注解@SerializedName(),否则会获取不到对应数据而显示null。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值