【问题标题】:JQ can't parse an Unicode emoji character. Is it valid JSON?JQ 无法解析 Unicode 表情符号字符。它是有效的 JSON 吗?
【发布时间】:2017-02-25 14:39:05
【问题描述】:

我有一个 JSON 文件,其中包含来自 Clojure 的 data.json 库的 JSON。数据来自人们似乎经常微笑的 Twitter。

$ 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 seems to suggest 应该成对出现:

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

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

【问题讨论】:

    标签: json unicode clojure standards jq


    【解决方案1】:

    JSON specification 说:

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

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

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

    所以可以这么说:

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

    2. jq 在此拥有其权利;

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

    “...去掉这些字符”

    参见例如How to remove non UTF-8 characters from text file

    【讨论】:

    • 我不认为这是对规范的唯一或正确解读。您的第二个引用来自标题为“字符串和字符问题”的部分;这只是指导:它没有对有缺陷的代理提出任何额外的一致性要求,它只是描述了客户端可能无法处理此类字符串。所需的行为似乎未指定,工作组已拒绝改进 erratum 3984 中的规范的请求。
    【解决方案2】:

    肯定是有效的json,但是代码单元D83D本身是无效的。请记住,jq 不仅仅是解释 json,它还试图获取它的值。所以这不再只是存储在 json 中的字符流,一旦被 jq 消费,它是一个具有确定值的字符串。

    该值是一个高替代值,它必须成对出现,而您的输入显然没有。因此,文件中编码的字符串虽然是有效的 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}
    

    然后你可以去掉它们或者对丢失的代理做一个最好的猜测。

    【讨论】:

    • 是的,由于数据来自 Clojure 库,我认为值得指出的是,Clojure 字符串由 UTF-16 chars 组成,因此错误数据实际上可能来自 data.json ,如果它不能正确处理代理对。确实,这曾经是 a bug in data.json,但很久以前就已修复。
    • 感谢您的指点。我想我知道发生了什么。我有时会按字符拆分 Java 字符串,那时我可能会孤立字符。
    • 谢谢!我应该指出,Java 有 Character.isSurrogate,我现在正在使用它。
    • @JeffMercado - 为避免混淆,也许您可​​以改写回复中的第一句话,以明确您指的是语法 (ABNF),而不是 JSON 标准指定的语义。
    猜你喜欢
    • 2021-09-14
    • 2019-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-10
    • 2015-05-09
    • 2017-08-24
    • 2011-11-02
    相关资源
    最近更新 更多