使用字符串中的原始字符转换 JSON

使用字符串中的原始字符转换 JSON

生成非法 JSON 的工具出现问题。

某些 JSON 字符串包含 00-1f 范围内的字符。所以我想将这些字符转换为\u00xx字符串中正确转义的值。

我能做到的最好的事情是:

cat test2.json | jq -aR . | sed -e 's/\\"/"/g' -e 's/^"\(.*\)"$/\1/' | jq

解释:

jq -aR                    reads the data as raw input and converts
                          the whole thing into a single string.
                          This converts all control characters into
                          the correct form => \u00xx

sed -e 's/^"\(.*\)"$/\1/' Removes the quotes from the beginning and end.

sed -e 's/\\"/"/g'        Looks for escaped quotes and removed the quotes.

jq                        Just makes it pretty again at the end.
                          Also makes sure it is valid JSON.

我发现了一些问题(但幸运的是还没有影响我)。

  1. 字符串中嵌入的 '\n' 未正确处理。
  2. 任何转义字符现在都可能是双重转义的。
  3. 可能还有其他我没有考虑过的事情。

一些测试数据可以通过以下方式生成:

echo -e "{ \"data\": \"XX\001YY\"}" > test2.json

然后我测试了:

cat test2.json | jq -aR . | sed -e 's/\\"/"/g' -e 's/^"\(.*\)"$/\1/' | jq

生成:

{
  "data": "XX\u0001YY"
}

newline只是注意到,当它位于字符串内部时,这不能正确处理=> '\n' => '\x0a' 。

答案1

您可以使用 perl 将所有 C0 控件替换为十六进制转义符:

perl -pe 's/([\x01-\x1f])/sprintf("\\u%04x", ord($1))/eg' < test.json

  1. 循环运行程序,最后打印结果 sed-style ( perl -pe)
  2. 匹配 01-1f 范围内的每个字节 ( s/([\x01-\x1f])/... g)
  3. 计算字节的序数值 ( ord($1))
  4. sprintf("\\u%04x", ord($1))将匹配的字节替换为( /e)的结果

这将插入\u0001, \u0002, ...,\u001f来代替匹配的字节。

将要以相同的方式转义所有换行符,因此如果文件有未加引号的换行符,它将中断(值得注意的是,文本文件将至少有一个终止换行符,但可以在之前或之后机械删除)。在这种情况下,[\x01-\x09\x0b-\x1f]将跳过它,但如果有则失败引号内真正的换行符。

如果您的文件同时包含带引号和不带引号的换行符,则这种无上下文替换无法工作。您将需要一个自由的 JSON 解析器,它按原样接受文件,以便知道哪些需要转义,哪些不需要。我不确定其中之一。

相关内容