从JSON文件中检测和解析转义字符“\”?

3

我在处理一个JSON文件时遇到了问题。我正在使用谷歌提供的以下链接。

http://www.google.com/finance/company_news?q=AAPL&output=json"

我的问题出现在想要解析数据并将其显示在屏幕上时。由于某些原因,数据不能被正确解码。
原始数据:
 1.) one which must have set many of the company\x26#39;s board on the edge of their
 2.) Making Less Money From Next \x3cb\x3e...\x3c/b\x3e

当我导入数据时,我会执行以下操作:
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();        
BufferedReader reader = new BufferedReader(new InputStreamReader(
                is, "iso-8859-1"), 8); 
StringBuilder sb = new StringBuilder();
String line = null;
        while ((line = reader.readLine()) != null) {
            sb.append(line + "n");
}
is.close();
json = sb.toString();

我收到的输出,使用org.json从json文件中提取数据,如下所示(注意缺少反斜杠):

1.)one which must have set many of the companyx26#39;s board on the edge of their
2.)Making Less Money From Next x3cbx3e...x3c/bx3e

我目前处理第一个问题的方法是这样的:

JSONRowData.setJTitle((Html.fromHtml((article.getString(TAG_TITLE).replaceAll("x26", "&")))).toString());

第二个问题我不太清楚(无恶意)。

我猜这个不起作用的原因是反斜杠被用作转义字符。我尝试了许多不同的方法来读取数据,但都没有成功。有没有一种方法可以导入数据以处理这个问题,而不使用正则表达式?


解决方案

我们今天的宿敌:"\x26" -- ASCII(十六进制表示法)

将原始数据读入Char数组。apache的commons.io库是实现此操作的好方法。一旦完成这一步骤,使用for循环读取Char数组,查找“\”,如果找到,则在下一个数组位置查找“x”。如果再次找到,则获取Char数组中的下两个字符。这两个字符是您的ASCII十六进制值。将十六进制转换为十进制形式,然后将十进制强制转换为Char。将此字符附加到字符串构建器。

如果没有匹配项(带有“\”),则将Char附加到字符串构建器。现在我们可以调用.toString()方法并将其转换为字符串。

从那里开始,数据可能包含一些HTML残留物(在本例中为'和/或)。使用Html.fromHtml()来处理这些内容。


请查看此链接:http://stackoverflow.com/a/8715600/645270。另外,您尝试过转义转义字符吗?(正如第二个答案中建议的那样) - keyser
@Keyser 我之前注意到了那个链接,但它并没有提供可行的解决方案。我可以转义这个转义字符,但那不是需要使用正则表达式将 "" 替换为 "\" 吗? - wdziemia
在答案下面有解决此问题的方法说明。 - wdziemia
让我想起了那个链接:p 很遗憾没有更好的解决方案。 - keyser
1个回答

3
这里的问题在于谷歌——至少是该URL——提供了无效的JSON1,2。尽管JSON库没有直接拒绝无效的JSON,但它以“好吧,让我们忽略这个\转义字符并继续”方式解析它。也就是说,不是渲染有问题,而是输入有误。

1字符串中不允许出现\x(除非\本身被转义),因为没有转义的\只能后跟一小组字符(其中不包括x)。字符代码的转义必须使用\u1234而不是\x12

我能想到的唯一“解决方法”是非常粗糙的黑客技巧:即读取原始文本并将\x12转换为\u0012。(实际上,这不是一个很糟糕的黑客技巧,因为不需要考虑上下文敏感的东西;但是,这不应该是必需的!Google丢人了。)
提取无效JSON字符串文字:
“Apple Inc.(NASDAQ:AAPL)股票继续领跑大型科技股票的表现,今年表现最佳。周一开始的重要事件之后,股票价格没有出现重大波动。”
(要使其有效,请将\x26替换为\u0026&。)
愉快的编码和--祝你好运 :)
在Java中,一种[未经测试的]方法可能是使用正则表达式(通过String.replaceAll):
inputString.replaceAll("\\x(\d{2})", "\\u00$1") 

我一直担心这个问题,我的一厢情愿总是让我失去理智。我会尝试使用原始数据,也许我可以从中解决问题。我可以将输入作为XML获取,但是数据被包裹在各种HTML标记中并且嵌套其中,非常混乱。感谢您的回复,我也会尝试向Google开发人员寻求答案。 - wdziemia
@wdziemia 实际上,那个JSON格式是各种错误的。我在问题中指出了错误,但键也不是JSON字符串,因此无效...看起来像是有人生成了“JavaScript对象字面量”,而不是JSON。我会尽量不再考虑它,因为这让我感到头痛:这家知名IT公司(据传充满了非常聪明的人)提供的服务引入了ProtocolBuffers... - user166390
搞定了,感谢您的帮助!将原始数据读入字符数组,然后将十六进制表示的ASCII字符替换为其对应的十进制值。然后将十进制值转换为字符。Html.fromHtml() 处理了任何剩余的 HTML 实体代码/HTML 标签。再次感谢! - wdziemia
@wdziemia,我很高兴你找到了解决方法。不过,我可能会尝试使用字符串而不是字符数组。我已经更新了我的帖子,并提供了一个小的[未经测试]示例,也许也可以起作用... - user166390
这太搞笑了。我刚刚访问了链接,发现键仍未加引号,可能还有其他问题。难道你们中没有人报告过这个问题吗?JSON很容易就能做对。我会明天报告它...也许。 - Esailija

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接