5

由于一些通信错误,我有时会收到带有一些非法字符的 JSON 字符串: "{messageType\" : \"Test1\", \"from\" : \"F2D0B5C6-9875-46B5-8D4F\"}����1"

这些非法字符使我的 JSON 解析器崩溃。我正在使用 RapidJSON JSON 解析器 (C/C++)。您能否告诉我是否有一种方法可以从字符串中过滤掉这些不需要的字符并验证 json 字符串的完整性。

4

5 回答 5

5

这不是解析器中的错误。解析器验证空终止符之前的尾随字符是空格。并且在发生错误时返回错误代码。但是如果没有空终止符,可能会导致分段错误,类似于strlen().

在较新版本的 RapidJSON 中,有一个kParseStopWhenDoneFlag. 启用后,解析器将在完整的 JSON 值后停止读取尾随字符。例如

Document d;
const char* s =
    "{messageType\" : \"Test1\", \"from\" : \"F2D0B5C6-9875-46B5-8D4F\"}����1";
d.Parse<kParseStopWhenDoneFlag>(s);
assert(!d.HasParseError());

通过使用此标志,解析器将在读取后停止},而不报告错误。

它尚未在指南中记录。请参考https://github.com/miloyip/rapidjson/pull/83中的讨论

于 2014-11-07T03:51:01.523 回答
2

提交错误报告。JSON 解析器应该接受您向其输入的任何输入并返回适当的错误消息。如果它崩溃了,这听起来像是一个漏洞,可以让你的应用程序受到黑客的攻击。可能最好找到一个不同的解析器。

接收方不应修改 JSON 数据以使其正常工作。应该按原样对待,如果它不是可接受的数据,则应该拒绝。如果由于代码中的错误而出现“通信错误”,请修复错误。如果它们是由于服务器错误引起的,请向编写服务器代码的人投诉。如果它们是真正的传输错误,您怎么知道您没有保持 JSON 有效的更改,例如付款金额从 100 美元更改为 900 美元?

于 2014-11-06T10:07:34.960 回答
2

我认为您应该考虑滚动您自己的预处理函数,该函数遍历 JSON 字符串中的每个字符,搜索不属于您的合法集的字符,然后将它们删除或替换为空格。然后将新修复的字符串转发给 RapidJSON。

最好首先检测您何时遇到通信问题(因此 JSON 可能不完整或不正确)并丢弃并重试整个会话,而不是按照您的意愿“修补”数据这里可以解决您的短期问题(程序崩溃),但很容易产生数据不一致和其他更微妙和难以诊断的问题。

此外,如果您在这样的字符串末尾看到大部分错误数据,我认为您应该仔细检查您的问题实际上与通信有关 - 您在此处给出的情况看起来更像是一个未正确终止的字符串缓冲区并且有额外的字符串结尾之后的垃圾(未初始化的内存) - 也许您希望 C++ 清除(设置为零)分配的缓冲区?

于 2014-11-06T09:32:44.893 回答
1

您可以列出字符串中允许的字符,并检查 json 流的每个字符是否在 allowed_string 中。例子 :

std::string allowed = "abcdefghijklmnopqrstuvwxyz0123456789.,{}[]\"";
std::string json = "{\"bar\":\"foo\",\"blah\":25}";
for(unsigned long int i = 0; i < json.length(); ++i)
  if(allowed.find(json[i]) == std::string::npos)
    throw IllegalJsonChar(json[i]);
于 2014-11-06T09:38:45.340 回答
1

如果您的系统符合 POSIX.1,您可以使用iconv.

您可以进行系统调用(Linux/iOS 等):

iconv -f utf-8 -t utf-8 -c file.txt

这将从 utf-8 转换为 utf-8 跳过任何无效字符。

您可以使用iconv(3)做同样的事情,但需要一点编程。

于 2014-11-06T09:49:33.267 回答