标题: 如何解析不规范的JSON数据?
时间: 2022-06-05发布,2022-06-05修改
解析某网站的API
数据,该数据表面上以JSON
形式返回,实际上像是人工直接拼接而成,如:
<?php
$chapters = ['第一章 开始', '第二章 过程', '第三章 结束'];
echo '[';
foreach ($chapters as $id => $name)
echo '{"id":' . $id . ',"name":"' . $name . '"},';
echo ']';
[{"id":0,"name":"第一章 开始"},{"id":1,"name":"第二章 中间"},{"id":2,"name":"第三章 结束"},]
大部分时候问题不大(处理末尾逗号即可),但出错的时候是真的棘手。搜集了一些出错的例子(简化):
[
{"name": "第五卷:"世家"子弟"}, # 这种情况出现最多,没转义『"』
{"name": "天下大乱(上)【\x06】"}, # 出现了 ASCII 0-31 的字符,json 规范是不允许的
{"name": "\"小白兔\"少爷"}, # 转义了不该转义的字符
{"name": "番外篇~\(≧▽≦)/~"}, # 同上
{"name": "权力的Chun\药"}, # 同上
{"name": 饮马江湖"}, # 搞不明白这是怎么出现的。是标题含有“退格符”(\x08),吃掉上一个『"』吗?
{"name": style="color:Gray;"}, # ???
{"name": ""}, # 最后一项末尾不能有『,』
]
『回复列表(45|隐藏机器人聊天)』
@20263,@无名啊,@淡然,当然对于引号不匹配这种问题,eval也无能为力,也只会得到错误。此时,如果想可靠地提取信息,可以考虑放弃格式分析,直接进行正则表达式内容匹配:
var json = `[
{"name": "第五卷:"世家"子弟"}, # 这种情况出现最多,没转义『"』
{"name": "天下大乱(上)【\x06】"}, # 出现了 ASCII 0-31 的字符,json 规范是不允许的
{"name": "\"小白兔\"少爷"}, # 转义了不该转义的字符
{"name": "番外篇~\(≧▽≦)/~"}, # 同上
{"name": "权力的Chun\药"}, # 同上
{"name": 饮马江湖"}, # 搞不明白这是怎么出现的。是标题含有“退格符”(\x08),吃掉上一个『"』吗?
{"name": style="color:Gray;"}, # ???
{"name": ""}, # 最后一项末尾不能有『,』
]`;
var results = json.matchAll(/\{"name":\s*"?(.*?)"?\},/gm);
for (var obj of results) {
console.log(obj[1]);
}
PHP版:
<?php
$json = <<<EOF
[
{"name": "第五卷:"世家"子弟"}, # 这种情况出现最多,没转义『"』
{"name": "天下大乱(上)【\x06】"}, # 出现了 ASCII 0-31 的字符,json 规范是不允许的
{"name": "\"小白兔\"少爷"}, # 转义了不该转义的字符
{"name": "番外篇~\(≧▽≦)/~"}, # 同上
{"name": "权力的Chun\药"}, # 同上
{"name": 饮马江湖"}, # 搞不明白这是怎么出现的。是标题含有“退格符”(\x08),吃掉上一个『"』吗?
{"name": style="color:Gray;"}, # ???
{"name": ""}, # 最后一项末尾不能有『,』
]
EOF;
preg_match_all('/\{"name":\s*"?(.*?)"?\},/m', $json, $results, PREG_SET_ORDER);
foreach ($results as $obj) {
echo $obj[1], "\n";
}
@幕后导演,@老虎会游泳,我改下措辞,这是某网站的APP
客户端的API
数据,应该不是在浏览器内解析的
上述例子的真实链接: