Оберните все цифры в 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"
}
В.К.
источник

Ответы:

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" }
Стефан
@ StéphaneChazelas Да, это превратит подобъекты в строки. Однако данная структура данных не содержит подобъектов.
Кусалананда
2
Не только подобъекты, все значения, включая массивы, логические значения и null(все же стоит отметить IMO, хотя в выборке OP этого нет).
Стефан
И как это изменить, если у меня есть массив?
VK
@ StéphaneChazelas Сортировка. Спасибо, что тыкаешь в меня.
Кусалананда
8

Вот простое решение на основе jtcутилиты Unix:

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

Предложенное решение будет корректно работать с произвольными структурированными jsons, например:

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реализует теперь шаблоны и пространства имен. При этом не требуется вызова внешней оболочки:

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, поэтому процитировал бы числа true, falseи null.

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"
}
Правин Кумар Б.С.
источник
@ Кусалананда исправил код
Правин Кумар Б.С.
почему ты используешь \{1,\},? Чтобы проверить, появляется ли элемент один или несколько раз, используйте +. И это не будет работать для чисел, таких как -123, 0xab, 0o12, 0b1011, 1e23 или 1.2e3 ...
phuclv
@phuclv \{1,\}- это BRE-эквивалент ERE +. Некоторые sedреализации поддерживают \+как расширение или параметр -Eили -rдля включения ERE, но это не переносимо. \?это еще одно \{0,1\}
Стефан
@phuclv вы не найдете без кавычек 0xab 0o12 0b1011 в действительном файле JSON.
Стефан