用引号将 JSON 中的所有数字括起来

用引号将 JSON 中的所有数字括起来

有一些 JSON 数据包含一些数值。如何将所有数字转换为字符串? (用引号括起来)

例子:

{
        "id":1,
        "customer":"user",
        "plate":"BMT-216-A",
        "country":"GB",
        "amount":1000,
        "pndNumber":20000,
        "zoneNumber":4
}

应该成为

{
        "id":"1",
        "customer":"user",
        "plate":"BMT-216-A",
        "country":"GB",
        "amount":"1000",
        "pndNumber":"20000",
        "zoneNumber":"4"
}

答案1

$ jq 'map_values(tostring)' file.json
{
  "id": "1",
  "customer": "user",
  "plate": "BMT-216-A",
  "country": "GB",
  "amount": "1000",
  "pndNumber": "20000",
  "zoneNumber": "4"
}

重定向到新文件,然后将其移至原始文件名。

为了更彻底地将非平面结构中的数字转换为字符串,请考虑

jq '(..|select(type == "number")) |= tostring' file.json

这将递归地检查给定文档中的每个值,并选择数字。然后将选定的值转换为字符串。严格来说,它还会查看键,但由于这些不能是 JSON 中的纯数字,因此不会选择任何键。

例子:

$ jq . file.json
{
  "a": {
    "b": 1
  },
  "b": null,
  "c": [
    1,
    2,
    "hello",
    4
  ]
}
$ jq '(..|select(type == "number")) |= tostring' file.json
{
  "a": {
    "b": "1"
  },
  "b": null,
  "c": [
    "1",
    "2",
    "hello",
    "4"
  ]
}

要另外引用null,请将 更改select()

select(type == "number" or type == "null")

答案2

这是一个基于的简单解决方案jtcUNIX实用程序:

bash $ jtc -w'<.*>D:' -eu echo '"{}"' \; file.json
{
   "amount": "1000",
   "country": "GB",
   "customer": "user",
   "id": "1",
   "plate": "BMT-216-A",
   "pndNumber": "20000",
   "zoneNumber": "4"
}
bash $ 

如果您想将更改直接应用到 json 文件中,请使用开关-f,如下所示:

bash $ jtc -f -w'<.*>D:' -eu echo '"{}"' \; file.json

所提出的解决方案将与任意结构化 json 一起正常工作,例如:

bash $ jtc -w'<.*>D:' -eu echo '"{}"' \; file.json
{
   "amount": "1000",
   "country": "GB",
   "customer": "user",
   "id": "1",
   "plate": "BMT-216-A",
   "pndNumber": "20000",
   "sub": {
      "subvalue": "123"
   },
   "zoneNumber": "4"
}
bash $ 
  • 如果你想引用空值,只需添加步行路径-w'<>n:'
  • 如果您想引用布尔值,请添加步行路径-w'<any>b:'

此外,反向任务(取消引用所有数字)可以通过类似的方式轻松实现:比如说,file.json已经“引用”,取消引用所有数字:

bash $ jtc -w'<^\d+$>R:' -eu echo {-} \; file.json
{
   "amount": 1000,
   "country": "GB",
   "customer": "user",
   "id": 1,
   "plate": "BMT-216-A",
   "pndNumber": 20000,
   "zoneNumber": 4
}
bash $ 

更新:最新版本jtc现在实现了模板和命名空间。这样就不需要调用外部 shell:

bash $ jtc -w'<.*>D:' -u'<.*>D:<val>v' -T'"{val}"' file.json
{
   "amount": "1000",
   "country": "GB",
   "customer": "user",
   "id": "1",
   "plate": "BMT-216-A",
   "pndNumber": "20000",
   "zoneNumber": "4"
}

jtc用户指南:https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md

答案3

perl -pe 's/("(?:\\.|[^"])*")|[^\s[\]{}:,"]+/$1||qq("$&")/ge' file.json

会引用任何未引用且不是 的内容[]{}:,whitespace,因此会引用数字truefalsenull

perl -pe 's/("(?:\\.|[^"])*")|-?\d+(?:\.\d+)?(?:[eE][-+]?\d+)?/$1||qq("$&")/ge'

将专门引用与 json 数字规范匹配且不在引号内的内容。

它们根据 JSON 规范进行精确的标记化,而不是近似值。

答案4

我尝试了下面的方法,效果很好。

我管道化了两次尝试达到我的水平来减少它

命令:

sed 's/[0-9]\{1,\},\?$/"&/g' filename |
sed '/[0-9]\{1,\}$/s/[0-9]\{1,\}/&"/g'|
sed '/[0-9]\{1,\},$/s/,$/"&/g`'

输出:

 {
        "id":"1",
        "customer":"user",
        "plate":"BMT-216-A",
        "country":"GB",
        "amount":"1000",
        "pndNumber":"20000",
        "zoneNumber":"4"
}

相关内容