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


11

有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"
}

Answers:


29
$ 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")

3
需要注意的是它改变了{"a":{"b":1},"b":null}{ "a": "{\"b\":1}", "b": "null" }
斯特凡Chazelas

@StéphaneChazelas是的,它将把子对象变成字符串。但是,给定的数据结构不包含子对象。
库萨兰达

2
不仅子对象,所有值,包括数组,布尔值和null(即使OP的样本中都没有这些值,仍然值得注意IMO)。
斯特凡Chazelas

以及如果我有一个数组怎么改变呢?
VK

@StéphaneChazelas排序。谢谢你戳我。
库萨兰达

8

这是一个基于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 $ 
  • 如果您想引用空值,只需抛出一个walk-path -w'<>n:'
  • 如果您想引用布尔值,则抛出一个walk-path -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 $ 

UPDATEjtc现在实现的最新版本是模板和名称空间。这样就不需要调用外部外壳程序了:

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


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

将引用任何不报价,是不是[]{}:,whitespace,所以就报数字,truefalsenull

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

将专门引用与json编号规范匹配的内容,而引号中尚未包含该内容。

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


-1

我尝试使用下面的方法,它工作正常。

我通过管道传输2次尝试达到我的水平以减少它

命令:

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"
}

@Kusalananda更正了代码
Praveen Kumar BS

你为什么用\{1,\},?要测试某个元素是否出现一次或多次,请使用+。而这不适用于-123、0xab,0o12、0b1011、1e23或1.2e3等数字
phuclv

@phuclv \{1,\}是ERE的BRE等效项+。有些sed实现支持\+扩展或启用ERE 的-Eor -r选项,但这不是可移植的。\?是另一个不可移植的扩展,虽然其标准相当于是\{0,1\}
斯特凡Chazelas

@phuclv,在有效的JSON文件中找不到未引用的0xab 0o12 0b1011数字。
斯特凡Chazelas
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.