当前位置: 首页 > news >正文

【Android】【bug】Json解析错误Expected BEGIN_OBJECT but was STRING...

前文

在 Android 开发中,JSON 解析是对接后端接口、处理设备数据时的常见操作,而 Gson 作为谷歌推出的 JSON 解析库,以其简洁高效被广泛使用。但在实际开发中,解析过程往往会遇到各种 “坑”,本文就以一次雷达数据解析为例,分享从报错到数据异常的完整解决过程。

一、初始问题:

解析时报 “Expected BEGIN_OBJECT but was STRING”

问题场景

项目中需要解析雷达设备通过 TCP 发送的 JSON 数据,数据格式如下:

{"topic":"/Radar/data","data":"{\"sn\":20250001,\"time\":\"2025-08-12-16:56:22\",\"X\":-2.2384777069091799,\"Y\":1.7031339406967164,\"Z\":0.0}"}

解析代码片段(初始版本):

// 直接尝试解析为内层数据类
RadarInfo radarInfo = gson.fromJson(dataString, RadarInfo.class);

运行后报错:

java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 32 path $.data
问题分析

从报错信息和数据格式可以看出,核心问题是JSON 结构嵌套方式不匹配:

外层 JSON 的data字段值被双引号包裹,实际是一个 “字符串形式的 JSON”(而非直接的 JSON 对象)

解析代码错误地将其当作 “嵌套的 JSON 对象” 处理,导致 Gson 预期接收一个对象(BEGIN_OBJECT),却收到了字符串(STRING)

解决方案:两步解析法

需要分两次解析,先处理外层 JSON,再解析内层字符串:

定义外层数据模型:

接收topic和字符串类型的data

private static class RadarData {private long sn;private String data; // 注意:这里是String类型,接收内层JSON字符串
}
先解析外层 JSON,获取data字段的字符串值
// 第一步:解析外层,得到包含data字符串的对象
RadarData radarData = gson.fromJson(dataString, RadarData.class);
再解析内层字符串,转换为实际数据对象
// 第二步:将data字符串解析为具体数据
RadarInfo radarInfo = gson.fromJson(radarData.data, RadarInfo.class);
二、新问题:解析成功但数据全为 0.0
问题场景

解决上述报错后,解析过程不再崩溃,但日志显示所有坐标值都为 0:

雷达数据位置X: 0.0
雷达数据位置Y: 0.0
雷达数据位置Z: 0.0
内层数据类定义(问题版本):
private static class RadarInfo {private String time;private double x;  // 小写xprivate double y;  // 小写yprivate double z;  // 小写z
}
问题分析

通过对比 JSON 数据和 Java 类发现:字段名大小写不匹配

原始 JSON 中坐标字段是大写的X、Y、Z(如"X":-2.2384777069091799)

数据类中定义的是小写的x、y、z

Gson 默认采用 “严格字段名匹配”(包括大小写),因此无法将 JSON 中的X映射到x,最终赋值为 double 类型的默认值 0.0

解决方案:统一字段映射关系

有两种方式可以解决字段名大小写问题:

方案一:修改属性名与 JSON 保持一致

直接将数据类的属性名改为大写,与 JSON 字段匹配:

private static class RadarInfo {private String time;private double X;  // 大写X,与JSON一致private double Y;  // 大写Y,与JSON一致private double Z;  // 大写Z,与JSON一致
}
方案二:使用@SerializedName注解(推荐)

通过注解指定 JSON 字段名,无需修改 Java 属性名,灵活性更高:

import com.google.gson.annotations.SerializedName;private static class RadarInfo {private String time;@SerializedName("X")  // 明确指定对应JSON中的"X"字段private double x;@SerializedName("Y")  // 明确指定对应JSON中的"Y"字段private double y;@SerializedName("Z")  // 明确指定对应JSON中的"Z"字段private double z;
}
三、总结:Gson 解析避坑指南

通过本次问题解决,我们可以总结出 Gson 解析 JSON 时的常见问题及排查思路:

结构不匹配报错(Expected BEGIN_OBJECT but was STRING)

检查是否为 “JSON 嵌套字符串形式的 JSON”,需分两次解析

确认外层字段类型(如data是 String 还是 Object)

数据为默认值(如 0、null)

检查字段名是否完全匹配(包括大小写、拼写)

核对数据类型是否一致(如 JSON 的 number 对应 Java 的 int/double,而非 String)

最佳实践

定义数据类时尽量使用@SerializedName注解,明确映射关系

解析嵌套 JSON 时,分步骤处理(先外层后内层)

遇到问题时,打印原始 JSON 和解析后的对象,对比排查字段映射问题

http://www.dtcms.com/a/326938.html

相关文章:

  • 计算机视觉(8)-纯视觉方案实现端到端轨迹规划(模型训练+代码)
  • 虚拟机一站式部署Claude Code 可视化UI界面
  • 401 Unauthorized(未授权)​​ 和 ​​403 Forbidden(禁止访问)区别
  • python --- 基础语法(1)
  • 《飞算Java AI:从安装到需求转实战项目详细教学》
  • 论文阅读:Agricultural machinery automatic navigation technology
  • Linux文件I/O操作全解析
  • 论文阅读(九)Locality-Aware Zero-Shot Human-Object Interaction Detection
  • window 右键菜单添加 vscode
  • PySpark性能优化与多语言选型讨论
  • 【论文阅读】从表面肌电信号中提取神经信息用于上肢假肢控制:新兴途径与挑战
  • 基于跨平台的svg组件编写一个svg编辑器
  • 【论文阅读】一种基于经典机器学习的肌电下肢意图检测方法,用于人机交互系统
  • Spark Core 3.3.2 略讲~
  • Elasticsearch JavaScript 客户端「基础配置」全指南(Node/TS)
  • 人工智能+虚拟仿真,助推医学检查技术理论与实践结合
  • 运维的一些指令
  • LINUX812 shell脚本:if else,for 判断素数,创建用户
  • 使用Excel制作甘特图
  • GitLab CI + Docker 自动构建前端项目并部署 — 完整流程文档
  • Web 开发 14
  • Linux环境gitlab多种部署方式及具体使用
  • 自建知识库,向量数据库 体系建设(二)之BERT 与.NET 8
  • Mac如何安装telnet命令
  • GIT使用攻略
  • 全面解析MySQL(5)——“索引、事务、JDBC”三大核心
  • WPF开发利器:MahApps.Metro 现代化UI框架
  • leetcode3258:统计满足K约束的子字符串数量Ⅰ(变长滑动窗口详解)
  • 文件IO(1)
  • Win10系统Ruby+Devkit3.4.5-1安装