Java中使用Gson解析json数据

前言

承接上篇文中,讲到eclipse开发环境中Gson的引入和基本使用;下面将讲述java中的网络编程和Gson对json字符串的解析:

  • **java 发送Http Get请求 **
  • java 发送Http send请求
  • 请求返回json数据的类构造

发送Http Get请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/**
* 向指定URL发送GET方法的请求
*
* @param url 发送请求的URL
* @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
* @return URL 所代表远程资源的响应结果
*/
public static String sendGet(String url, String param) {
String result = "";
BufferedReader in = null;
try {
String urlNameString = url + "?" + param;
URL realUrl = new URL(urlNameString);
// 打开和URL之间的连接
URLConnection connection = realUrl.openConnection();
// 设置通用的请求属性
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");

// 建立实际的连接
connection.connect();
// 获取所有响应头字段
Map<String, List<String>> map = connection.getHeaderFields();
// 遍历所有的响应头字段
for (String key : map.keySet()) {
// System.out.println(key + "--->" + map.get(key));
}
// 定义 BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送GET请求出现异常!" + e);
e.printStackTrace();
}
// 使用finally块来关闭输入流
finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}

return result;
}

发送Http send请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/**
* 向指定 URL 发送POST方法的请求
*
* @param url 发送请求的 URL
* @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
* @return 所代表远程资源的响应结果
*/
public static String sendPost(String baseUrl, String md5, String jsonStr) {
OutputStreamWriter out = null;
BufferedReader in = null;
String result = "";

try {
URL realUrl = new URL(baseUrl + "?sign=" + md5);
// 打开和URL之间的连接
// URLConnection conn = realUrl.openConnection();
HttpURLConnection conn = (HttpURLConnection) realUrl
.openConnection();

// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setInstanceFollowRedirects(true);
conn.setUseCaches(true);

conn.setRequestMethod("POST");
conn.setConnectTimeout(18000);
conn.setInstanceFollowRedirects(true);
conn.setRequestProperty("Accept", "application/json");// 设置接受报文的格式
conn.setRequestProperty("Content-Type", "text/plain");// 设置发送的格式

// 获取URLConnection对象对应的输出流
conn.connect();

out = new OutputStreamWriter(conn.getOutputStream());
out.write(jsonStr);
out.flush();

in = new BufferedReader(new InputStreamReader(
conn.getInputStream(), "UTF-8"));

String line = null;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送 POST 请求出现异常!" + e);
e.printStackTrace();
}
// 使用finally块来关闭输出流、输入流
finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}

return result;
}

实例测试

可以在百度API Store中请求一些天气状况数据,返回json字符串;
eg:

1
2
3
4
5
6
7
8
9
10
public class MainTest {
public static void main(String[] args) {
// api store随便查找的请求的天气数据
final String baseUrl = "http://apistore.baidu.com/microservice/weather";
final String param = "citypinyin=zhengzhou";
final String jsonStr = HttpUtil.sendGet(baseUrl, param);

System.out.println(jsonStr);
}
}

返回得到的是json字符串:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
errNum: 0,
errMsg: "success",
retData: {
city: "北京", //城市
pinyin: "beijing", //城市拼音
citycode: "101010100", //城市编码
date: "15-02-11", //日期
time: "11:00", //发布时间
postCode: "100000", //邮编
longitude: 116.391, //经度
latitude: 39.904, //维度
altitude: "33", //海拔
weather: "晴", //天气情况
temp: "10", //气温
l_tmp: "-4", //最低气温
h_tmp: "10", //最高气温
WD: "无持续风向", //风向
WS: "微风(<10m/h)", //风力
sunrise: "07:12", //日出时间
sunset: "17:44" //日落时间
}
}

json字符串转java对象的类构造

我们需要构造相应结构的java类,并生成相应的对象,方可使用Gson进行相应的解析,根据上述请求的得到的json字符串,具体构造方法如下:

<1> 将json字符串中的单一键值对(key-value)表示成类的属性;
<2> 将json字符串中的“{}”包围的结构,构造成另一个类;
<3> 将json字符串中的"[]"包围的结构,构造成数组,通常使用List<>。
<4> 构造类中的属性名称,一定要与json字符串中的名称一致(特别重要, 由Gson的方法所限制

那么,对于上述的天气json字符串,我们的构造过程如下所示:

构造整体类结构

(1) 构造一个Weather类,含有3个私有属性:(注意:属性名称和json字符串中的key的名称一样);
(2) 添加相应的构造方法、Getter和Setter方法;

1
2
3
private int errNum;             // 错误标志
private String errMsg; // 错误信息
private RetData retData; // 对象类型的请求具体数据

具体结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class Weather {
private int errNum; // 错误标志
private String errMsg; // 错误信息
private RetData retData; // 请求具体数据

public Weather() {
}

public Weather(int errNum, String errMsg, RetData retData) {
this.errNum = errNum;
this.errMsg = errMsg;
this.retData = retData;
}

public int getErrNum() {
return errNum;
}

public void setErrNum(int errNum) {
this.errNum = errNum;
}

public String getErrMsg() {
return errMsg;
}

public void setErrMsg(String errMsg) {
this.errMsg = errMsg;
}

public RetData getRetData() {
return retData;
}

public void setRetData(RetData retData) {
this.retData = retData;
}
}

同理,json字符串中的retData天气数据的构造如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
public class RetData {
private String city; // 城市名称
private String pinyin; // 城市拼音
private String citycode; // 城市编号
private String date; // 日期
private String time; // 时间
private String postCode; // 邮编
private String longitude; // 经度
private String latitude; // 纬度
private String altitude; // 海拔
private String weather; // 天气状况
private String temp; // 温度
private String l_tmp; // 低温
private String h_tmp; // 高温
private String WD; // 风向
private String WS; // 风速
private String sunrise; // 日出时间
private String sunset; // 日落时间

public RetData() {
}

public RetData(String city, String pinyin, String citycode, String date, String time, String postCode, String longitude, String latitude, String altitude, String weather, String temp, String l_tmp, String h_tmp, String WD, String WS, String sunrise, String sunset) {
this.city = city;
this.pinyin = pinyin;
this.citycode = citycode;
this.date = date;
this.time = time;
this.postCode = postCode;
this.longitude = longitude;
this.latitude = latitude;
this.altitude = altitude;
this.weather = weather;
this.temp = temp;
this.l_tmp = l_tmp;
this.h_tmp = h_tmp;
this.WD = WD;
this.WS = WS;
this.sunrise = sunrise;
this.sunset = sunset;
}

public String getCity() {
return city;
}

public void setCity(String city) {
this.city = city;
}

public String getPinyin() {
return pinyin;
}

public void setPinyin(String pinyin) {
this.pinyin = pinyin;
}

public String getCitycode() {
return citycode;
}

public void setCitycode(String citycode) {
this.citycode = citycode;
}

public String getDate() {
return date;
}

public void setDate(String date) {
this.date = date;
}

public String getTime() {
return time;
}

public void setTime(String time) {
this.time = time;
}

public String getPostCode() {
return postCode;
}

public void setPostCode(String postCode) {
this.postCode = postCode;
}

public String getLongitude() {
return longitude;
}

public void setLongitude(String longitude) {
this.longitude = longitude;
}

public String getLatitude() {
return latitude;
}

public void setLatitude(String latitude) {
this.latitude = latitude;
}

public String getAltitude() {
return altitude;
}

public void setAltitude(String altitude) {
this.altitude = altitude;
}

public String getWeather() {
return weather;
}

public void setWeather(String weather) {
this.weather = weather;
}

public String getTemp() {
return temp;
}

public void setTemp(String temp) {
this.temp = temp;
}

public String getL_tmp() {
return l_tmp;
}

public void setL_tmp(String l_tmp) {
this.l_tmp = l_tmp;
}

public String getH_tmp() {
return h_tmp;
}

public void setH_tmp(String h_tmp) {
this.h_tmp = h_tmp;
}

public String getWD() {
return WD;
}

public void setWD(String WD) {
this.WD = WD;
}

public String getWS() {
return WS;
}

public void setWS(String WS) {
this.WS = WS;
}

public String getSunrise() {
return sunrise;
}

public void setSunrise(String sunrise) {
this.sunrise = sunrise;
}

public String getSunset() {
return sunset;
}

public void setSunset(String sunset) {
this.sunset = sunset;
}
}

至此,我们的类结构的构造定义完成了,下面调用Gson的fromJson()方法(具体原理是java的反射机制)便可以生成相应的变量在内存中使用。

综合测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class MainTest {
public static void main(String[] args) {
// api store随便查找的请求的天气数据
final String baseUrl = "http://apistore.baidu.com/microservice/weather";
final String param = "citypinyin=zhengzhou";
final String jsonStr = HttpUtil.sendGet(baseUrl, param);

System.out.println(jsonStr);

Gson gson = new Gson();
Weather weather = gson.fromJson(jsonStr, Weather.class);
RetData retData = weather.getRetData();

System.out.println("weather = " + weather.getErrNum());
System.out.println("weather = " + weather.getErrMsg());

System.out.println("retData = " + retData.getH_tmp());
System.out.println("retData = " + retData.getL_tmp());

System.out.println("retData = " + retData.getTemp());
System.out.println("retData = " + retData.getWD());
System.out.println("retData = " + retData.getWeather());
System.out.println("retData = " + retData.getWeather());
}
}
0%