JQ 无法解析 Unicode 表情符号字符。它是有效的 JSON 吗?

问题描述 投票:0回答:3

我有一个 JSON 文件,其中包含来自 Clojure 的

data.json
库的 JSON。数据来自推特,人们似乎经常微笑。

$ cat /tmp/myfile | jq .

我得到:

parse error: Invalid \uXXXX\uXXXX surrogate pair escape at line 1, column 14862268

违规部分是:

$ cut -c 14862258-14862269 /tmp/2017-02-23-2
79-7\ud83d",

所以,这个转义码是在真实的 JSON 文件中找到的,而 JQ 无法读取它。

echo '"\ud83d"' | jq .

Fileformat.info 似乎建议它应该成对出现:

SMILING FACE WITH OPEN MOUTH
"\uD83D\uDE03"
  1. 这真的是在 JSON 文件中查找的无效字符吗?我的 JSON 在技术上无效吗?

  2. 是否有一个简单的实用程序可以在 JQ 之前通过管道传输数据以去除这些字符?或者我可以让JQ放宽它的解释吗?

json unicode clojure standards jq
3个回答
7
投票

JSON 规范 说:

字符串是零个或多个 Unicode 字符 [UNICODE] 的序列。

从这个意义上说,字符串“\ud83d”不是有效的 JSON(“+UD83D 不是有效的 Unicode 字符”),即使它符合 JSON ABNF。正如标准文档继续指出的,字符串规范和 ABNF 之间存在差异:

本规范中的 ABNF 允许成员名称和 包含无法编码 Unicode 的位序列的字符串值 人物;例如,“\uDEAD”(单个未配对的 UTF-16 代理人)。已经观察到这种情况的实例,例如,当 库截断 UTF-16 字符串而不检查是否 截断分裂代理对。软件的行为 接收包含此类值的 JSON 文本是不可预测的...

所以可以公平地说:

  1. “\uD83D”不是严格有效的 JSON,即使它符合 ABNF;

  2. jq 在此享有其权利;

  3. jsonlint 接受“\uD83D”是错误的。

“...去掉这些字符”

参见例如 如何从文本文件中删除非 UTF-8 字符


2
投票

它绝对是有效的 json,但代码单元

D83D
本身是无效的。请记住,jq 不仅仅是解释 json,它还试图获取它的值。因此,一旦被 jq 使用,它就不再只是存储在 json 中的字符流,而是一个具有确定值的字符串。

该值是一个高代理,它必须成对出现,而您的输入显然没有。因此,文件中编码的字符串虽然是有效的 json,但并不代表 jq 尝试解析的有效 unicode 字符串。

如果您希望能够使用 jq 解析它,您需要检查 json 并完成对。


如果您至少可以确保它是有效的 json,您可能可以使用正则表达式来扫描数据以搜索不匹配的代理。像这样的东西:

\\u[Dd][89ABab][0-9A-Fa-f]{2}(?!\\u[Dd][C-Fc-f][0-9A-Fa-f]{2})
|
(?<!\\u[Dd][89ABab][0-9A-Fa-f]{2})\\u[Dd][C-Fc-f][0-9A-Fa-f]{2}

然后你可以将它们脱掉,或者对丢失的代理进行最佳猜测。


0
投票

改用 yq (https://github.com/mikefarah/yq),它可以在 jq 失败的大型数据集上不会出现解析错误。

© www.soinside.com 2019 - 2024. All rights reserved.