章节索引
前提
在 索引文章 中我提到过,我会写一篇文章来讲JSONObject和JSONArray,这篇文章会总结JSONObject用来传递键不重复的单个数据时的用法,并介绍用JSONArray传递一数组或者一列表值的用法。学习这篇文章之前,请先把前面整套帖子中的程序跑通,这篇文章是作为进阶补充的。
JSONObject
首先让我们总结一下在之前的文章中,我们是怎么实用JSONObject在客户和服务器两端互相传值的。
(一)客户端向服务端传递数据
以登录请求中传递账号密码为例:
①客户端封装(在Volley的getParams函数中)
@Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("AccountNumber", accountNumber);
params.put("Password", password);
return params;
}
②服务端解封装(在Servlet的doPost函数中)
String accountNumber = request.getParameter("AccountNumber").trim();
String password = request.getParameter("Password").trim();
(二)服务端向客户端传递数据
①服务端封装(在(一)②的同一个doPost函数中)
Map<String, String> params = new HashMap<>();
JSONObject jsonObject = new JSONObject();
if (verifyResult) { //这个bool值是登录验证函数传回的结果
params.put("Result", "success");
} else {
params.put("Result", "failed");
}
jsonObject.put("params", params);
out.write(jsonObject.toString());
②客户端解封装(在(一)①的同一个Volley类下的onResponse函数中)
public void onResponse(String response) {
try {
JSONObject jsonObject = (JSONObject) new JSONObject(response).get("params");
String result = jsonObject.getString("Result");
if (result.equals("success")) {
//TODO:做登录成功的操作
} else {
//TODO:做登录失败的操作
}
} catch (JSONException e) {
//TODO:做http请求异常的操作
}
}
JSONArray
前面的部分属于总结,接下来的JSONArray就到了这篇文章的重点。
首先构建以下场景:
我们在使用一个书籍阅读APP,APP启动时会向服务器发出请求,请求所有书籍的信息列表。每一本书籍包含书名、作者、页数等信息。
①BookDAO中的查询函数(注意返回值类型)
public static JSONArray queryAll() {
JSONArray books = new JSONArray(); //注①
//获得数据库的连接对象
Connection connection = DBManager.getConnection();
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
//生成SQL代码
StringBuilder sqlStatement = new StringBuilder();
sqlStatement.append("SELECT * FROM book");
//设置数据库的字段值
try {
preparedStatement = connection.prepareStatement(sqlStatement.toString());
resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
JSONObject book = new JSONObject(); //注②
book.put("Title", resultSet.getString("Title"));
book.put("Author", resultSet.getString("Author"));
book.put("PageCount", resultSet.getInt("PageCount"));
books.add(book);
}
return books;
} catch (SQLException ex) {
Logger.getLogger(BookDAO.class.getName()).log(Level.SEVERE, null, ex);
return null;
} finally {
DBManager.closeAll(connection, preparedStatement, resultSet);
}
}
注释①: 注意这里的类型是JSONArray,作为返回值用的;
注释②: 注意这里的类型是JSONObject,代表一个条目,即一本书;
②服务端封装(在Servlet的doPost函数中)
这里只需要调用①中的函数,把得到的JSONArray对象封装到JSONObject中传回去即可。
Map<String, JSONArray> params = new HashMap<>();
JSONObject jsonObject = new JSONObject();
JSONArray books = BookDAO.queryAll();
params.put("Books", books);
jsonObject.put("params", params);
out.write(jsonObject.toString());
③客户端解封装步骤1(在Volley的onResponse函数中)
JSONObject jsonObject = (JSONObject) new JSONObject(response).get("params");
JSONArray books = jsonObject.getJSONArray("Books");
④客户端解封装步骤2(解析JSONArray,在使用上述books对象中的数据时)
ArrayList<Book> bookInfos = new ArrayList<>(); //注①
for (int i = 0; i < books.length(); i++) {
JSONObject jsonObject = books.getJSONObject(i); //注②
Book book = new Book(); //注③
book.setTitle(jsonObject.getString("Title"));
book.setAuthor(jsonObject.getString("Author"));
book.setPageCount(jsonObject.getInt("PageCount"));
bookInfos.add(book);
}
注释①: bookInfos作为ArrayList对象,存储了所有书目的对象信息,一行即是一本书;
注释②: 每次从JSONArray中取出一行,即一个JSONObject对象,用来解析;
注释③: 用于存储解析后的一本书信息的Java Bean对象。
后记
学会了JSONArray之后,我们在APP的功能上关于数据传递方面就可以比较完整地实现了。