已掉线,重新登录

首页 > 绿虎论坛 > 历史版块 > 编程 > 其他编程语言 > 讨论/求助

标题: 如何解析不规范的JSON数据?

作者: @Ta

时间: 2022-06-05发布,2022-06-05修改

点击: 17305

解析某网站的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": "\&quot;小白兔\&quot;少爷"},  # 转义了不该转义的字符
    {"name": "番外篇~\(≧▽≦)/~"},        # 同上
    {"name": "权力的Chun\药"},             # 同上
    {"name": 饮马江湖"},                   # 搞不明白这是怎么出现的。是标题含有“退格符”(\x08),吃掉上一个『"』吗?
    {"name": style="color:Gray;"},         # ???
    {"name": ""},                          # 最后一项末尾不能有『,』
]

[隐藏样式|查看源码]


『回复列表(45|隐藏机器人聊天)』

1.

先求助万能虎,@老虎会游泳

有没有可能用正则规范它们

(/@Ta/2022-06-05 22:35//)

2.

我觉得正则规范它们可能是开发/运行效率最高的一个

自己写解析器,怕又慢又不保证正确

(/@Ta/2022-06-05 22:41//)

3.

去除末尾逗号的正则,我已经写了(前提是其他内容都是正确的

模式:("(?:\\?.)*?")|,\s*([]}])
替换:\1\2

(/@Ta/2022-06-05 22:46//)

4.

截取?

(/@Ta/2022-06-05 22:53//)

5.

说起这个json,我原生js获取正常,拿这个uniapp写,搞了一天都没解析成,睡前搜到了几篇文章,明天看看

(/@Ta/2022-06-05 22:56//)

6.

@20263

  • 截取啥?
  • uniapp。。是小程序的吗?不支持JSON.parse()
(/@Ta/2022-06-05 22:59//)

7. 哪个网站?
(/@Ta/2022-06-06 09:13//)

8. 遇到不规范的json真恼火
(/@Ta/2022-06-06 09:20//)

9.

@无名啊,如果是合法的JS代码,在JS里可以用eval解析:

var obj = eval('return ' + json);

就能完成解析。

不要忘记JSON的全称:JavaScript Object Notation,JavaScript对象表示法。

合法的JSON一定是合法的JavaScript对象。

不合法的JSON,既然网站在用,那浏览器肯定能解析,所以通常也是合法的JavaScript对象。

(/@Ta/2022-06-06 12:48//)

10.

@淡然@20263,如果运行环境是浏览器JavaScript,并且不怕任意代码执行漏洞,那就使用eval解析嘛。发送给浏览器的看起来像JSON但实际不是的,都是JSON的前身:JavaScript对象表达式。

正是因为Web程序员都喜欢向前端输出JavaScript对象表达式来实现信息传递,所以有人对JavaScript对象表达式进行了规范,添加了语法限制,于是得到了我们如今使用的JSON:JavaScript对象表示法(JavaScript Object Notation)。

(/@Ta/2022-06-06 11:53//)

11.

@20263@无名啊@淡然,当然对于引号不匹配这种问题,eval也无能为力,也只会得到错误。此时,如果想可靠地提取信息,可以考虑放弃格式分析,直接进行正则表达式内容匹配:

var json = `[
    {"name": "第五卷:"世家"子弟"},         # 这种情况出现最多,没转义『"』
    {"name": "天下大乱(上)【\x06】"},    # 出现了 ASCII 0-31 的字符,json 规范是不允许的
    {"name": "\&quot;小白兔\&quot;少爷"},  # 转义了不该转义的字符
    {"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]);
}

Screenshot_20220606_123323.jpg

(/@Ta/2022-06-06 12:54//)

12.

PHP版:

<?php
$json = <<<EOF
[
    {"name": "第五卷:"世家"子弟"},         # 这种情况出现最多,没转义『"』
    {"name": "天下大乱(上)【\x06】"},    # 出现了 ASCII 0-31 的字符,json 规范是不允许的
    {"name": "\&quot;小白兔\&quot;少爷"},  # 转义了不该转义的字符
    {"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";
}

Screenshot_20220606_125243.jpg

(/@Ta/2022-06-06 12:53//)

13.
(/@Ta/2022-06-06 12:53//)

14.

@无名啊,鉴于内容不是合法的JS代码(引号不匹配),所以正则表达式可能是最佳方案。

\{"name":\s*"?(.*?)"?\},

11楼和12楼的效果非常好。


https://regex101.com/

Screenshot_20220606_125858_com.android.chrome.jpg

(/@Ta/2022-06-06 12:59//)

15.

@无名啊,你的真实数据在name旁边还有其他字段,得修改一下正则表达式。

(/@Ta/2022-06-06 13:01//)

16.

@老虎会游泳,直接提取name不太够,真实数据结构大概是:

  • API结果信息
  • 数据
    • 书本信息
      • 卷1信息
        • 章节1信息
        • 章节2信息
      • 卷2信息
        • ……

书本、卷、章节信息都希望得以保留(重新生成目录所需嘛)

(/@Ta/2022-06-06 13:03//)

17.

@无名啊,顺便一提,你无法解析的时候,那个网站的客户端估计也是无法解析的,你可以去试试

(/@Ta/2022-06-06 13:03//)

18.

@无名啊,所以,可以考虑采用社会工程学解决这个问题,向他们反馈app有Bug,让他们自己修复

(/@Ta/2022-06-06 13:04//)

19.

@无名啊,name可以用正则表达式得到,其他字段当然也可以,只是表达式变得更复杂而已。

(/@Ta/2022-06-06 13:04//)

下一页 1/3页,共45楼

回复需要登录

9月25日 06:14 星期四

本站由hu60wap6驱动

备案号: 京ICP备18041936号-1