Оберніть усі цифри в 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 Так, це перетворило б об'єкти в рядки. Однак дана структура даних не містить під-об'єктів.
Kusalananda

2
Не тільки суб-об'єкти, всі значення, включаючи масиви, булеві і null(все-таки варто відзначити ІМО, хоча зразок ОП не має жодного з них).
Стефан Шазелас

І як це змінити, якщо у мене є масив?
ВК

@ StéphaneChazelas Відсортовано. Дякую, що тикався на мене.
Kusalananda

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

@Kusalananda виправив код
Praveen Kumar BS

для чого ти користуєшся \{1,\},? Щоб перевірити, чи з’являється елемент, використовуйте один чи більше разів +. І це не працюватиме для таких цифр, як -123, 0xab, 0o12, 0b1011, 1e23 або 1.2e3 ...
phuclv

@phuclv \{1,\}- BRE еквівалент ERE +. Деякі sedреалізації підтримують \+як розширення або як -Eабо -rопцію для включення ERE, але це не є портативним. \?це ще одне не портативне розширення, хоча стандартний еквівалент\{0,1\}
Стефан Шазелас

@phuclv у дійсному файлі JSON ви не знайдете котируваних номерів 0xab 0o12 0b1011.
Стефан Шазелас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.