gson 抛出 MalformedJsonException

Posted

技术标签:

【中文标题】gson 抛出 MalformedJsonException【英文标题】:gson throws MalformedJsonException 【发布时间】:2012-07-14 02:56:48 【问题描述】:

我正在使用 gsonjson 字符串转换为 Java-Object。 result2 的值与result1 的值完全相同。 (从调试器复制;添加了反斜杠)

转换result1时抛出以下异常: com.google.gson.JsonSyntaxException:com.google.gson.stream.MalformedJsonException:预期 EOF 在第 1 行第 170 列

转换 result2 工作正常。

json字符串根据jsonlint.com有效。

public static Userinfo getUserinfo()

    String result1 = http.POST("https://www.bitstamp.net/api/balance/",
                                postdata, true);
    String result2 = "\"btc_reserved\": \"0\", \"fee\": \"0.5000\", \"btc_available\": \"0.10000000\", \"usd_reserved\": \"0\", \"btc_balance\": \"0.10000000\", \"usd_balance\": \"30.00\", \"usd_available\": \"30.00\"";
    Gson gson = new Gson();
    Userinfo userinfo1 = gson.fromJson(result1, Userinfo.class); //throws Exception
    Userinfo userinfo2 = gson.fromJson(result2, Userinfo.class); //works fine

    return userinfo1;

private class Userinfo 

    public Userinfo()
    

    public float usd_balance;
    public float btc_balance ;
    public float usd_reserved;
    public float btc_reserved;
    public float usd_available;
    public float btc_available;
    public float fee;
    public float last_update;

【问题讨论】:

【参考方案1】:

我怀疑 result1 末尾有一些字符,您在调试器中看不到关闭 字符之后的字符。 result1result2 的长度是多少?我会注意到您引用的 result2 有 169 个字符。

当对象末尾有额外的字符不是空格时,GSON 会抛出该特定错误,并且它定义空格 very 狭义(如 JSON 规范那样) - 仅 \t\n\r 和空格算作空白。 请特别注意,结尾的 NUL (\0) 字符不算作空格,会导致此错误

如果您无法轻松找出导致末尾多余字符的原因并消除它们,另一种选择是告诉 GSON 以宽松模式解析:

Gson gson = new Gson();
JsonReader reader = new JsonReader(new StringReader(result1));
reader.setLenient(true);
Userinfo userinfo1 = gson.fromJson(reader, Userinfo.class);

【讨论】:

谢谢!我的 HTTP 类将 json 字符串下载到 256 字节的字符缓冲区中,然后将其转换为字符串(result1)。因此,result1 的长度为 255 而不是 169。 我遇到了同样的问题;异常中的整个 EOF 事情让我感到震惊,我的问题只是纯粹且简单的格式错误的 JSON。 我遇到了同样的问题,但是我通过 FileChannel 获得了我的 JSON。我很确定编码没问题。我所做的是从硬盘上的文件中调用 String red 的 trim() 方法,这解决了问题。 @ThePaul - 您的字符串末尾可能有额外的 NUL(即 '\0')字符。 String.trim() 不仅删除空格,还删除任何小于 32 的字符,而 GSON 将这些字符视为尾随垃圾。 (然后它抱怨“我看到了右括号,所以接下来应该看到一个 EOF,但我看到了一些其他的东西”) 确保你正在导入正确的 json 阅读器,其他库具有相同名称的类【参考方案2】:

根据我最近的经验,JsonReader#setLenient 基本上使解析器非常宽容,甚至允许格式错误的 JSON 数据。

但对于从您受信任的 RESTful API 检索到的某些数据,此错误可能是由尾随空格引起的。在这种情况下,只需trim 数据即可避免错误:

String trimmed = result1.trim();

那么gson.fromJson(trimmed, T) 可能会起作用。当然,这只涵盖了一种特殊情况,所以 YMMV。

【讨论】:

嗨@ryenus,如果我有两个单词中间有空格,那该怎么办? 如果空格在字符串响应中很重要怎么办?在这种情况下,tirming 是不好的。您将失去数据的完整性。【参考方案3】:

在调试器中您不需要添加反斜杠,输入字段可以理解特殊字符。

在java代码中你需要转义特殊字符

【讨论】:

我从调试器中复制了 result1 的值,然后添加了反斜杠以转义 result2 中的特殊字符;) 是否有空格字符或 \n\r 前面或附加到 json 字符串。应该很简单 result1.equals(result2)的结果是什么? @ProgrammerBruce:result1.equals(result2)=false。两个字符串都包含相同的字符,但 result1 比 result2 长(由我的 http 类引起;见上文)。

以上是关于gson 抛出 MalformedJsonException的主要内容,如果未能解决你的问题,请参考以下文章

gson.toJson() 抛出 ***Error

在Grails中使用带有rest配置文件的gson时,String列表抛出ClassCastException

为啥 Gson fromJson 会抛出 JsonSyntaxException: Expected BEGIN_OBJECT but was BEGIN_ARRAY?

使用Gson解析json

ADT 和 SDK 工具更新到 v17 后的 Gson NoClassDefFoundError

Retrofit请求数据对错误以及网络异常的处理