對比原生 org.json 與 Google Gson 解析同一 JSON 資料的代碼量與可維護性,結論顯而易見:有 Gson 沒人願意寫原生解析。
{
"status": "000000",
"desc": null,
"detail": [
{"id": 1, "xhid": 100, "author": "張三", "content": "內容1", "picUrl": "url1", "status": "1"},
{"id": 2, "xhid": 101, "author": "李四", "content": "內容2", "picUrl": "url2", "status": "1"}
]
}
public static void jsonParse(String json) {
List<Detail> details = new ArrayList<>();
try {
JSONObject obj = new JSONObject(json);
if ("000000".equals(obj.getString("status"))) {
if ("null".equals(obj.getString("desc"))) {
details = parseArray(details, obj);
for (Detail d : details) System.out.println(d);
}
}
} catch (JSONException e) { e.printStackTrace(); }
}
private static List<Detail> parseArray(List<Detail> list, JSONObject obj) throws JSONException {
JSONArray arr = obj.getJSONArray("detail");
for (int i = 0; i < arr.length(); i++) {
JSONObject item = arr.getJSONObject(i);
int id = item.getInt("id");
int xhid = item.getInt("xhid");
String author = item.getString("author");
String content = item.getString("content");
String picUrl = item.getString("picUrl");
String status = item.getString("status");
list.add(new Detail(id, xhid, author, content, picUrl, status));
}
return list;
}
缺點:層層 getJSONObject/getJSONArray、手動映射每個欄位、try-catch 繁雜、欄位名寫錯只能運行時發現。
public class Info {
private String status;
private String desc;
private List<Detail> detail; // 對應 JSON "detail" 陣列
// 必須有無參建構子 + getter/setter
}
public class Detail {
private int id;
private int xhid;
private String author;
private String content;
private String picUrl;
private String status;
// 建構子、getter/setter、toString()...
}
public static void gsonParse(String json) {
Gson gson = new Gson();
Info info = gson.fromJson(json, Info.class); // 核心:自動映射
if ("000000".equals(info.getStatus()) && info.getDesc() == null) {
for (Detail d : info.getDetail()) {
System.out.println(d);
}
}
}
String jsonArray = "[{\"name\":\"李四\",\"age\":40},{\"name\":\"張三\",\"age\":20}]";
// 錯誤寫法:泛型擦除導致 List<Object>
// List list = gson.fromJson(jsonArray, List.class);
// 正確:TypeToken 捕獲泛型資訊
TypeToken<List<User>> token = new TypeToken<List<User>>() {};
List<User> users = gson.fromJson(jsonArray, token.getType());
String nested = "{\"status\":\"ok\",\"data\":[{\"name\":\"李四\",\"age\":30},{\"name\":\"張三\",\"age\":20}]}";
class Wrapper {
private String status;
private List<User> data;
// getter/setter...
}
Wrapper w = gson.fromJson(nested, Wrapper.class);
if ("ok".equals(w.getStatus())) {
for (User u : w.getData()) System.out.println(u);
}
User[] users = {new User("張三",20), new User("李四",30), new User("王五",40)};
String json = gson.toJson(users);
// [{"name":"張三","age":20},{"name":"李四","age":30},{"name":"王五","age":40}]
List<User> list = Arrays.asList(users);
String json2 = gson.toJson(list); // 同樣結果
| 維度 | org.json | Gson |
|---|---|---|
| 代碼量 | 大量樣板代碼 | 極少(聲明式) |
| 類型安全 | 運行時才報錯 | 編譯期檢查 POJO |
| 維護性 | 欄位變更需改多處 | 只改 POJO 即可 |
| 效能 | 較低 | 高(流式解析可選) |
| 功能豐富度 | 基礎 | 註解配置、自訂 TypeAdapter、null 處理、日期格式化等 |
Gson 依賴:
com.google.code.gson:gson:2.10+。有 Gson 誰還用原生解析?