今天由于项目(Android)中的新需求,需要对服务端请求的Json数据包进行解析,头一次做这个有点被卡住了,钻了一下午才算弄通。下面用两个例子来展示如果使用Google提供的Gson来解析Json数据。
文章中不做太多解释,自己认真看看一定能看明白。
只有自己憋出来的才是自己的。 —— 高尔基
使用OKHttp发送网络请求,使用Gson解析反馈Json数据包,所以需要在项目中导入第三方库OkHttp和Gson,导入方法不介绍,Github上有。
这里采用的是百度地图提供的“WEB 服务API”,关于他的使用方式自己看下。
WEB 服务API(普通IP定位)地址:http://lbsyun.baidu.com/index.php?title=webapi/ip-api
下面上代码,只有核心代码。
//(经纬度)使用ip地址通过BaiduMapApi获取经纬度数据
private void getLocationDataFromBaiduMapApi() {
String strHttpCommand = "https://api.map.baidu.com/location/ip?&ak=您的AK&coor=bd09ll";
Log.w("NetWork", "Location 请求:" + strHttpCommand);
Utils_Http.sendOkHttpRequest(strHttpCommand, new okhttp3.Callback() {
@Override
public void onResponse(Call call, Response response) throws IOException {
String responseData = response.body().string();
Log.w("NetWork", "Location 请求结果:" + responseData);
// 解析反馈的定位信息
parseJsonWithGson_Location(responseData);
}
@Override
public void onFailure(Call call, IOException e) {
Log.w("NetWork", "Location 请求异常:" + e.toString());
}
});
}
//(经纬度)使用GSON解析JSON数据(解析百度ip定位数据)
private void parseJsonWithGson_Location(String jsonData) {
// 初始化GSON
Gson gson = new Gson();
MyClass_Gson_Location gson_location = gson.fromJson(jsonData, MyClass_Gson_Location.class);
// 地理位置信息请求成功
if (gson_location.getStatus() == 0) {
MyClass_Gson_Location.ContentBean contentBean = gson_location.getContent();
MyClass_Gson_Location.ContentBean.PointBean pointBean = contentBean.getPoint();
Log.w("NetWork", "经度x: " + pointBean.getX()); // 经度
Log.w("NetWork", "纬度y: " + pointBean.getY()); // 纬度
}
// 地理位置信息请求失败
else {
Log.w("NetWork", "status: " + gson_location.getStatus());
Log.w("NetWork", "message: " + gson_location.getMessage());
}
}
新建 MyClass_Gson_Location.class
public class MyClass_Gson_Location {
// 反馈数据示例
/* {
* address: "CN|北京|北京|None|CHINANET|1|None", #详细地址信息
* content: #结构信息
* {
* address: "北京市", #简要地址信息
* address_detail: #结构化地址信息
* {
* city: "北京市", #城市
* city_code: 131, #百度城市代码
* district: "", #区县
* province: "北京市", #省份
* street: "", #街道
* street_number: "" #门牌号
* },
* point: #当前城市中心点
* {
* x: "116.39564504", #当前城市中心点经度
* y: "39.92998578" #当前城市中心点纬度
* }
* },
* status: 0 #结果状态返回码
* }
*/
private String address;
private ContentBean content;
private int status;
private String message;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public ContentBean getContent() {
return content;
}
public void setContent(ContentBean content) {
this.content = content;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public static class ContentBean {
/*
* address : 北京市 #简要地址信息
*
* address_detail : city: "北京市", #城市
* city_code: 131, #百度城市代码
* district: "", #区县
* province: "北京市", #省份
* street: "", #街道
* street_number: "" #门牌号
*
* point : x: "116.39564504", #当前城市中心点经度
* y: "39.92998578" #当前城市中心点纬度
*
* status : 0 #结果状态返回码
*/
private String address; // 简要地址信息
private AddressDetailBean addressDetail; // 结构化地址信息
private PointBean point; // 当前城市中心点
private String status; // 结果状态返回码
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public AddressDetailBean getAddressDetail() {
return addressDetail;
}
public void setAddressDetail(AddressDetailBean addressDetail) {
this.addressDetail = addressDetail;
}
public PointBean getPoint() {
return point;
}
public void setPoint(PointBean point) {
this.point = point;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public static class AddressDetailBean {
/*
* city: "北京市", #城市
* city_code: 131, #百度城市代码
* district: "", #区县
* province: "北京市", #省份
* street: "", #街道
* street_number: "" #门牌号
*/
private String city;
private String cityCode;
private String district;
private String province;
private String street;
private String street_number;
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCityCode() {
return cityCode;
}
public void setCityCode(String cityCode) {
this.cityCode = cityCode;
}
public String getDistrict() {
return district;
}
public void setDistrict(String district) {
this.district = district;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getStreet_number() {
return street_number;
}
public void setStreet_number(String street_number) {
this.street_number = street_number;
}
}
public static class PointBean {
/*
* x: "116.39564504", #当前城市中心点经度
* y: "39.92998578" #当前城市中心点纬度
*/
private String x;
private String y;
public String getX() {
return x;
}
public void setX(String x) {
this.x = x;
}
public String getY() {
return y;
}
public void setY(String y) {
this.y = y;
}
}
}
}
如果仔细看的话,很容易看出来他是分层解析的,每一层定义一个内部类,类中的属性就是我们要获取的数据。这里我只需要经纬度数据,其它的数据获取方式一样。
这里采用的是心知天气提供的“心知API接口”,关于他的使用方式自己看下。
心知API接口 地址:https://www.seniverse.com/api
下面上代码,只有核心代码。
public static final String URL_SENICERSE_WEATHER = "https://api.seniverse.com/v3/weather/now.json?key=自己申请的key";
//(天气)根据ip获取当地天气(采用心知天气)
private void getWeatherInfo_IP() {
String strHttpCommand = Constant.URL_SENICERSE_WEATHER + "&location=ip" + "&language=zh-Hans&unit=c";
Log.d("NetWork", "Weather 请求:" + strHttpCommand);
Utils_Http.sendOkHttpRequest(strHttpCommand, new okhttp3.Callback() {
@Override
public void onResponse(Call call, Response response) throws IOException {
String responseData = response.body().string();
Log.d("NetWork", "Weather 请求结果:" + responseData);
// 解析反馈的天气信息
parseJsonWithGson_Weather(responseData);
}
@Override
public void onFailure(Call call, IOException e) {
Log.d("NetWork", "Weather 请求异常:" + e.toString());
}
});
}
//(天气)使用GSON解析JSON数据(解析心知天气数据)
private void parseJsonWithGson_Weather(String jsonData) {
// 初始化GSON
Gson gson = new Gson();
MyClass_Gson_Weather gson_weather = gson.fromJson(jsonData, MyClass_Gson_Weather.class);
List results = gson_weather.getResults();
for (MyClass_Gson_Weather.ResultsBean res : results) {
MyClass_Gson_Weather.ResultsBean.LocationBean locationBeans = res.getLocation();
// Log.d("Tag", "id: " + locationBeans.getId());
// Log.d("Tag", "name: " + locationBeans.getName());
// Log.d("Tag", "country: " + locationBeans.getCountry());
// Log.d("Tag", "path: " + locationBeans.getPath());
// Log.d("Tag", "timezone: " + locationBeans.getTimezone());
// Log.d("Tag", "timezone_offset: " + locationBeans.getTimezone_offset());
MyClass_Gson_Weather.ResultsBean.NowBean nowBean = res.getNow();
// Log.d("Tag", "天气现象文字: " + nowBean.getText());
// Log.d("Tag", "天气现象代码: " + nowBean.getCode());
// Log.d("Tag", "温度: " + nowBean.getTemperature() + " ℃");
// Log.d("Tag", "天气更新时间: " + res.getLast_update());
}
}
新建 MyClass_Gson_Weather.class
import java.util.List;
public class MyClass_Gson_Weather {
private List results;
public List getResults() {
return results;
}
public void setResults(List results) {
this.results = results;
}
public static class ResultsBean {
/**
* location : {"id":"WW5QJDVC4NKQ", "name":"北京", "country":"CN", "path":"北京,北京,中国", "timezone":"Asia/Shanghai", "timezone_offset":"+08:00"}
* now : {"text":"晴", "code":"0", "temperature":"-2"}
* last_update : 2018-01-09T09:25:00+08:00
*/
private LocationBean location;
private NowBean now;
private String last_update;
public LocationBean getLocation() {
return location;
}
public void setLocation(LocationBean location) {
this.location = location;
}
public NowBean getNow() {
return now;
}
public void setNow(NowBean now) {
this.now = now;
}
public String getLast_update() {
return last_update;
}
public void setLast_update(String last_update) {
this.last_update = last_update;
}
public static class LocationBean {
/**
* id : WW5QJDVC4NKQ
* name : 北京
* country : CN
* path : 北京,北京,中国
* timezone : Asia/Shanghai
* timezone_offset : +08:00
*/
private String id;
private String name;
private String country;
private String path;
private String timezone;
private String timezone_offset;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getTimezone() {
return timezone;
}
public void setTimezone(String timezone) {
this.timezone = timezone;
}
public String getTimezone_offset() {
return timezone_offset;
}
public void setTimezone_offset(String timezone_offset) {
this.timezone_offset = timezone_offset;
}
}
public static class NowBean {
/**
* text : 晴
* code : 0
* temperature : -2
*/
private String text;
private String code;
private String temperature;
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getTemperature() {
return temperature;
}
public void setTemperature(String temperature) {
this.temperature = temperature;
}
}
}
}
这个Weather数据和Location数据的解析是有区别的,不知到您有没有发现,MyClass_Gson_Weather.class中声明了一个List,这是MyClass_Gson_Location.class中没有的。
提取解析数据也不一样,Weather 中遍历了 List。
// 初始化GSON
Gson gson = new Gson();
MyClass_Gson_Weather gson_weather = gson.fromJson(jsonData, MyClass_Gson_Weather.class);
List results = gson_weather.getResults();
for (MyClass_Gson_Weather.ResultsBean res : results) {...}
而提取 Location 数据则没有遍历List。
// 初始化GSON
Gson gson = new Gson();
MyClass_Gson_Location gson_location = gson.fromJson(jsonData, MyClass_Gson_Location.class);
因为这两个服务端反馈的数据格式不同。
Location 请求结果:{“address”:“CN|\u5c71\u4e1c|\u67a3\u5e84|None|UNICOM|0|0”,“content”:{“address”:"\u5c71\u4e1c\u7701\u67a3\u5e84\u5e02",“address_detail”:{“city”:"\u67a3\u5e84\u5e02",“city_code”:172,“district”:"",“province”:"\u5c71\u4e1c\u7701",“street”:"",“street_number”:""},“point”:{“x”:“117.27930538”,“y”:“34.80788308”}},“status”:0}
Weather 请求结果:{“results”:[{“location”:{“id”:“WW5QJDVC4NKQ”,“name”:“北京”,“country”:“CN”,“path”:“北京,北京,中国”,“timezone”:“Asia/Shanghai”,“timezone_offset”:"+08:00"},“now”:{“text”:“多云”,“code”:“4”,“temperature”:“9”},“last_update”:“2018-11-11T22:45:00+08:00”}]}
仔细看可以看到 Weather 的数据中包含 [ 中括号 ],表示有多个同级的数据包,每个数据包里又有子数据包。而 Location 的数据就只有一个大数据包,大数据包里又有子数据包。所以 Weather 数据就得遍历 List。
弄明白这两个例子后,其实觉得也没啥,就是分层解析,一层就是一个类,到最后要获取的数据就是类中的属性,采用get方法提取出来。如果同一层中有多个数据那就放到List中并遍历List。到最后就是感觉有点麻烦,别也没啥。
如有错误欢迎指正,谢谢! ?