在行動/嵌入式環境,資料交換格式的選擇直接影響頻寬、CPU、電量與開發效率:
| 格式 | 優點 | 缺點 | 適用性 |
|---|---|---|---|
| 自定二進位 | 極致緊湊、效能最佳 | 非標準、難除錯、維護成本高 | 極度受限環境、專用協定 |
| XML | 標準化、工具豐富、自描述 | 冗長、解析耗資源 (DOM/SAX)、記憶體佔用大 | 企業整合、Web Services、文件導向 |
| JSON | 輕量、可讀、原生對應資料結構、解析快、跨語言 | 無 Schema 驗證 (可用 JSON Schema 補足)、不支援二進位 (需 Base64) | 行動應用、AJAX、REST API 首選 |
結論:JSON 在「輕量」與「標準」間取得最佳平衡,極適合 J2ME (客戶端) ↔ J2EE (伺服器端) 架構。
+----------------+ HTTP/POST (JSON) +----------------+
| J2ME Client | <------------------------> | J2EE Server |
| (MIDP/CLDC) | Request / Response | (Servlet/EJB) |
+----------------+ +----------------+
| |
| 1. Serialize Model → JSON | 1. Deserialize JSON → Model
| 2. HTTP POST | 2. Business Logic / DB
| 3. Receive Response | 3. Serialize Result → JSON
| 4. Deserialize JSON → Model | 4. HTTP Response
v v
+----------------+ +----------------+
| RMS Cache | | Database / |
| (Offline) | | External API |
+----------------+ +----------------+
org.json (J2EE 版) 或 Jackson/Gson (現代專案推薦)
// 1. 簡單物件: {"title":"news","count":10}
JSONObject json = new JSONObject(requestBody);
String title = json.getString("title");
int count = json.getInt("count");
// 2. 巢狀物件: {"header":{"title":"news","ver":1},"body":...}
JSONObject header = json.getJSONObject("header");
String title = header.getString("title");
// 3. 陣列: {"items":[{"id":1},{"id":2}]}
JSONArray items = json.getJSONArray("items");
for (int i = 0; i < items.length(); i++) {
JSONObject item = items.getJSONObject(i);
// ...
}
public class JsonServlet extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 讀取請求本文
StringBuilder sb = new StringBuilder();
BufferedReader br = req.getReader();
String line;
while ((line = br.readLine()) != null) sb.append(line);
String requestJson = sb.toString();
// 反序列化與業務邏輯
JSONObject reqObj = new JSONObject(requestJson);
String action = reqObj.getString("action");
JSONObject result = processAction(action, reqObj);
// 回應
resp.setContentType("application/json; charset=UTF-8");
resp.getWriter().write(result.toString());
}
private JSONObject processAction(String action, JSONObject params) {
JSONObject resp = new JSONObject();
try {
if ("queryUser".equals(action)) {
// JDBC 查詢...
JSONArray users = new JSONArray();
// users.put(userObj)...
resp.put("status", "ok");
resp.put("users", users);
} else {
resp.put("status", "error");
resp.put("message", "Unknown action");
}
} catch (Exception e) {
resp.put("status", "error");
resp.put("message", e.getMessage());
}
return resp;
}
}
JSONObject req = new JSONObject();
req.put("action", "queryUser");
req.put("token", authToken);
// 巢狀物件
JSONObject filters = new JSONObject();
filters.put("city", "Taipei");
filters.put("ageMin", 18);
req.put("filters", filters);
// 陣列
JSONArray ids = new JSONArray();
ids.put(101); ids.put(102);
req.put("ids", ids);
String requestBody = req.toString();
// 發送 HTTP POST...
String responseBody = ...; // 從 HTTP 讀取
JSONObject resp = new JSONObject(responseBody);
String status = resp.getString("status");
if ("ok".equals(status)) {
JSONArray users = resp.getJSONArray("users");
for (int i = 0; i < users.length(); i++) {
JSONObject u = users.getJSONObject(i);
String name = u.getString("name");
int age = u.getInt("age");
// 建立 Model 物件...
}
} else {
String msg = resp.getString("message");
// 顯示錯誤...
}
application/json; charset=UTF-8status 欄位區分| 需求 | 方案 |
|---|---|
| 二進位資料 (圖片/檔案) | Base64 編碼內嵌 JSON,或改用 Multipart/Related |
| 資料驗證 | 伺服端引入 JSON Schema (如 Everit JSON Schema) |
| 版本演進 | JSON 欄位新增不破壞相容性;重大變更用版本號 v=2 路由 |
| 離線同步 | 客戶端 RMS 佇列待同步操作,上線後批次重放 |
| 效能監控 | 記錄序列化/解析耗時、傳輸大小、錯誤率 |
JSON 以其輕量、高效、跨平台特性,成為 J2ME/J2EE 異構架構下資料交換的最佳實踐。本文提供的框架涵蓋序列化/反序列化、Servlet/MIDlet 實作模式、傳輸協定設計與擴充策略,可直接作為專案基礎架構參考。