使用Gson/Java解析Alpha Vantage API时的JSON格式异常排查
我来帮你排查这个问题——你遇到的JsonSyntaxException本质是获取到的JSON内容不符合标准格式,核心原因很明确,咱们一步步拆解:
问题根源
从你提供的API响应片段能看到,所有的双引号都被替换成了HTML转义实体",比如原本的"Meta Data"变成了"Meta Data"。而标准JSON要求必须用双引号"来包裹键和字符串值,Gson根本无法识别"这种格式,所以直接抛出了格式错误异常。
为什么会出现这种情况?大概率是你获取响应内容的方式不对:你用了response.body().toString(),如果是用OkHttp这类HTTP客户端,这个方法返回的是ResponseBody对象的内存地址字符串(比如okhttp3.ResponseBody@123456),但你说内容看起来正常,可能是你用的客户端返回了经过HTML转义的内容,或者你在传递过程中不小心做了转义处理。
解决方案
1. 先修复响应内容的获取方式
如果用的是OkHttp,正确获取响应文本的方式是调用string()方法,而不是toString():
// 正确的获取方式 String stringResponse = response.body().string();
⚠️ 注意:response.body().string()只能调用一次,因为ResponseBody的输入流会在调用后关闭,重复调用会报错。
2. 还原HTML转义的双引号
如果确认获取到的字符串里确实有",先把它替换成标准双引号:
stringResponse = stringResponse.replaceAll(""", "\"");
3. 验证JSON合法性
在解析前,先打印修复后的字符串,或者用本地的JSON校验逻辑确认内容是标准JSON格式。比如修复后的内容应该是这样的:
{ "Meta Data": { "1. Information": "Intraday (5min) open, high, low, close prices and volume", "2. Symbol": "IBM", ... }, "Time Series (5min)": { ... } }
4. 确认实体类定义的正确性
你的TimeSeriesStocks类定义是没问题的:
@SerializedName("Meta Data")和JSON里的键完全匹配- 使用
LinkedTreeMap来接收动态键值对是合理的,因为Alpha Vantage的返回里时间戳是动态的
如果后续想换成自定义对象,比如给Meta Data定义一个实体类,也是可行的,比如:
public class MetaData { @SerializedName("1. Information") public String information; @SerializedName("2. Symbol") public String symbol; // 其他字段同理 } public class TimeSeriesStocks { @SerializedName("Meta Data") public MetaData metaData; @SerializedName("Time Series (5min)") public LinkedTreeMap<String, LinkedTreeMap<String, String>> timeSeriesMap; }
总结
最可能的触发点是你错误地使用了response.body().toString()获取响应内容,导致拿到的不是真实的JSON文本。先修复这个获取逻辑,再处理转义问题,Gson就能正常解析了。
内容的提问来源于stack exchange,提问作者john_conner

