本人刚入门,有错误请评论指出
一、Json相关知识点
什么是Json?
Json的语法规则
Json的值可以是以下格式:
Json的例子“
{
"employees": [
{ "firstName":"John" , "lastName":"Doe" },
{ "firstName":"Anna" , "lastName":"Smith" },
{ "firstName":"Peter" , "lastName":"Jones" }
]
}
最外层花括号为一个对象Object,里层有一个键为”employees“,对应的值为一个数组,数组中又包含三个对象Object,分别用来描述每个员工的姓名,包含三个字符串类型的键值对。
二、如何解析Json格式的数据
返回Json格式的API:http://guolin.tech/api/weather?cityid=CN101280601&key=077b0519028e413ebfda3fad3d142dd4
顺便介绍一个解析和格式化Json的在线网站,挺好用的
https://www.json.cn/
此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数据,都是由数组和对象组成的,所以解析的时候也重点关注对象和数组的层级结构就好。
在Android中利用JsonObject解析数据
Android中请求网络API我使用的是OkHttp的开源库,可以去GitHub上搜索
请求网络数据的代码
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();
}
}
}
解析网络请求返回的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数据解析就比较麻烦了。
在Android中利用Gson来解析
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来重命名
利用网络请求返回的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。