伺服器回傳 JSON:
{
"return": "[{\"ambient\":2999,\"devLocation\":\"客廳\",...}]"
}
客戶端直接 new JSONObject(response) 拋出 Unterminated object at character ...。
return。return 的值是字串 (String),而非 JSONArray。字串內容為 JSON 陣列的字面序列化文字(含轉義引號)。JSONObject 解析時,解析器遇到 return 後的雙引號以為字串結束,實際上字串內部還有未轉義的結構字元,導致解析器狀態機錯亂。// 1. 先解析最外層
JSONObject outer = new JSONObject(responseString);
// 2. 取得內層字串
String innerJsonString = outer.getString("return"); // 內容為 "[{...},{...}]"
// 3. 再解析內層字串為 JSONArray
JSONArray dataArray = new JSONArray(innerJsonString);
// 4. 遍歷陣列取得每個物件
for (int i = 0; i < dataArray.length(); i++) {
JSONObject item = dataArray.getJSONObject(i);
int ambient = item.getInt("ambient");
String location = item.getString("devLocation");
// ... 其他欄位
}
伺服器不應將 JSON 陣列「字串化」後再放入另一個 JSON 物件。正確做法:
// 錯誤寫法 (雙重序列化)
JSONArray jArray = JSONArray.fromObject(envList);
return jArray.toString(); // 回傳字串,框架再包一層 {"return": "..."}
// 正確寫法 (直接回傳 List/陣列,讓框架序列化一次)
return envList; // 或 Map{ "data": envList }
若無法修改伺服器,客戶端務必採用「兩次解析」策略。
org.json 時注意 getString vs optString:前者缺鍵拋異常,後者回傳預設值。Gson / Moshi / Kotlinx.serialization,自動處理巢狀結構且效能更佳。JSONArray 建構子可正確處理,無需手動反轉義。「JSON 字串套 JSON 字串」是典型的雙重序列化錯誤。客戶端解決方法:先 JSONObject 取鍵值,再 JSONArray 解析該字串值。長遠來看,應要求伺服器修正序列化邏輯,避免雙重編碼。