首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用jq保持JSON字符串值中的转义正斜杠

用jq保持JSON字符串值中的转义正斜杠
EN

Unix & Linux用户
提问于 2023-02-26 19:36:52
回答 2查看 1.6K关注 0票数 4

根据JSON规范,不必用反斜杠转义正斜杠,但它们可以转义。我有一个JSON文件,其中所有字符串值中的正斜杠都是出于兼容的原因(但不是在键内)转义的:

代码语言:javascript
复制
{
  "proto://some/path": "\/\/some\/path"
}

但是,jq会自动删除这些反斜杠:

代码语言:javascript
复制
$ echo '{"proto://some/path":"\/\/some\/path"}' | jq -c .
{"proto://some/path":"//some/path"}

我需要输出为{"proto://some/path":"\/\/some\/path"}

How我可以告诉 jq to不更改任何字符串值并保留这些反斜杠吗?或者,是否有一种方法只在经过jq后才将这些反斜杠重新添加到值中?

EN

回答 2

Unix & Linux用户

回答已采纳

发布于 2023-02-26 20:12:25

如果你能的话我会很惊讶的。jq解码其输入,执行其操作,并将结果对象编码为json。在编码和输出时,它输出用\编码的字符串,而在/s前面有D2S的信息早就丢失了。同样的情况也会发生在最初写\u002f/s身上。您会发现,出于同样的原因,jq还将1.0重新格式化为11e2100INF1.7976931348623157e+308等。

但是,JSON是一种相对容易的文件格式,可以使用perl等手工可靠地处理。

要在所有字符串(对象键除外)中的每个\s之前添加/ S,您可以这样做:

代码语言:javascript
复制
jq... |
  perl -0777 -pe '
    s{"(?:\\.|.)*?"(\s*:)?}{
      $1 ? A14 : A14 =~ s{/}{\\/}gr
    }ge'

这应该是正确的,即使你有字符串嵌入",S和\s (如{"key": "//\"//\\"})。

作为jq的另一种选择,您可以使用JSON::PP perl模块,它可以被告知转义斜杠(尽管在所有字符串中都是这样):

代码语言:javascript
复制
$ json_pp -json_opt escape_slash < your-file
{"proto:\/\/some\/path":"\/\/some\/path"}

如果您已经熟悉perl,那么学习曲线将比必须学习jq语法要小得多。

在任何情况下,尽管JSON格式允许/s作为\/ (或与任何字符类似的\u002f )被转义,但它们并不需要转义。根据我在网上看到的内容,这是允许的,这样就可以通过编写将包含</code>的JSON字符串嵌入到HTML标记中。这就是为什么一些JSON编码器将这些<code>\/</code>编码为<code>/</code>,因为这使得它更易于移植。但是,如果这个JSON不像HTML那样被嵌入,那么它可能并不重要。如果是的话,您很可能希望在任何地方都有这种编码,包括在对象键中。</div>

票数 4
EN

Unix & Linux用户

发布于 2023-02-26 20:13:37

我假设某个进程没有意识到在JSON中编码字符串的必要性,而是插入了他们认为需要存储的文字字符串,而没有对其进行编码。由于反斜杠是转义不需要转义的字符,而且由于没有反斜杠本身转义文字反斜杠,所以当jq用于提取和解码字符串时,或者当它出于其他原因处理文档时,反斜杠看起来会“消失”。

简而言之,正斜杠不一定要转义(逃避它们实际上是一种不操作),但是如果您想将反斜杠保持为文字反斜杠,则反斜杠必须是反斜杠。

下面以递归的方式将文档中所有字符串值中的每个/转换为\\/ (这是用JSON字符串编写\/的方式)。记住,当jq表达式处理数据时,jq解析器已经删除了反斜杠。

代码语言:javascript
复制
jq 'walk(if type == "string" then gsub("/"; "\\/") else . end)' file

对于给定的示例文档,这将生成

代码语言:javascript
复制
{
  "proto://some/path": "\\/\\/some\\/path"
}

从修改后的文档中提取和解码编码的字符串值将为您提供\/\/some\/path

代码语言:javascript
复制
$ jq 'walk(if type == "string" then gsub("/"; "\\/") else . end)' file | jq -r '."proto://some/path"'
\/\/some\/path

如果从零开始创建相同的JSON文档,如下所示:

代码语言:javascript
复制
$ jq -n --arg 'proto://some/path' '\/\/some\/path' '$ARGS.named'
{
  "proto://some/path": "\\/\\/some\\/path"
}
票数 2
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/737018

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档