如何转换非标准键值对格式响应字符串以访问内部players与lobbies数据
非标准响应字符串的处理方案
接口返回的响应本质是Java集合类直接调用toString()生成的输出,完全不符合标准JSON规范,直接传入JSONObject会直接抛出解析异常,需要先完成格式转换才能正常读取内部字段。
该类非标准结构与标准JSON的核心差异
- 键值对分隔符使用
=,而非标准JSON的: - 所有字符串类型值(房间名称、用户名、房间公告等)没有双引号包裹,部分值里的空格被替换为
+ - 所有整数值被转为带多余
.0后缀的浮点格式(如1329.0实际对应整数1329) - 你提供的示例响应本身存在截断,末尾结构不完整,缺失多个闭合括号
- 响应顶层不存在代码里尝试读取的
data字段,顶层直接包含players、lobbies两个根节点
具体转换实现
1. 格式替换逻辑
按照差异点逐段处理原始字符串:
- 全局把键值对之间的
=替换为JSON标准的:分隔符 - 把值内部的
+替换回空格,还原用户名、公告里的空格 - 给所有被识别为纯文本的字符串值补全双引号包裹
- 移除所有整数值后面多余的
.0后缀 - 补全截断缺失的闭合括号,修复不完整的JSON结构
2. 可复用的转换工具方法
private String convertRawResponseToValidJson(String rawResponse) { // 替换键值对分隔符 String processed = rawResponse.replace("=", ":"); // 还原转义的空格 processed = processed.replace("+", " "); // 给纯文本类型的字符串值补双引号 processed = processed.replaceAll( ":(\\s*)([a-zA-Z0-9!\\.\\s,\\-]+?)(\\s*)(,|\\}|\\])", ":\"$2\"$3$4" ); // 移除整数值后多余的.0后缀 processed = processed.replaceAll("(\\d+)\\.0", "$1"); // 修复示例中末尾截断的残缺结构 processed = processed.replaceAll("comment:\\s*\\}", "comment: \"\"}}"); return processed; }
3. 修正后的正常解析流程
转换完成后即可正常读取字段,调整后的请求解析代码片段:
try (Response response = client.newCall(request).execute()) { String responseData = response.body().string(); // 先完成格式转换 String validJson = convertRawResponseToValidJson(responseData); JSONObject json = new JSONObject(validJson); // 直接读取顶层字段 int totalPlayers = json.getInt("players"); JSONArray lobbies = json.getJSONArray("lobbies"); // 遍历lobbies读取每个房间的信息 for (int i = 0; i < lobbies.length(); i++) { JSONObject lobby = lobbies.getJSONObject(i); int lobbyId = lobby.getInt("id"); String lobbyName = lobby.getString("name"); JSONArray lobbyPlayers = lobby.getJSONArray("players"); // 按需读取其余维度的字段即可 } } catch (Exception ex) { Log.d("ParseError", String.valueOf(ex)); }
额外注意事项
- 如果转换后仍存在解析失败,优先检查网络读取逻辑是否把完整响应体读完:你提供的示例字符串末尾结构残缺,是典型的响应读取不完整、提前截断导致的
- 如果接口返回的文本里本身包含
=、+等特殊符号,需要调整正则的匹配范围,避免全局替换误伤内容 - 因为这类输出本质是服务端用Java集合的
toString方法生成的,属于服务端接口实现的疏漏,长期来看更合理的方案是推动服务端返回真正的标准JSON格式,而非依赖客户端做大量字符串兼容
内容的提问来源于stack exchange,提问作者John Shiveley
相关产品推荐
相关产品推荐

