Wrap all numerics in JSON with quotes

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

Redirect to a new file and then move that to the original filename.

For a more thorough conversion of numbers in non-flat structures into strings, consider

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

This would examine every value recursively in the given document, and select the ones that are numbers. The selected values are then converted into strings. It would also, strictly speaking, look at the keys, but since these can't be plain numbers in JSON, no key would be selected.

Example:

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

To additionally quote the null, change the select() to

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

here's an easy solution based on jtc unix utility:

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 $ 

if you like to apply changes right into the json file, use the -f switch, like this:

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

The proposed solution will work correctly with an arbitrary structured jsons, e.g.:

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 $ 
  • if you like to quote null values, just throw in a walk-path -w'<>n:'
  • if you like to quote boolean values, throw in a walk-path -w'<any>b:'

Also, the reverse task (unquote all the numerics) is easily achieved in the similar way: say, file.json is already "enquoted", to unquote all the numerics:

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 $ 

UPDATE: the latest version of jtc implements now templates and namespaces. With that no invocation of external shell is required:

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 user guide: https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md


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

Would quote anything that is not quoted and is not []{}:,whitespace, so would quote numbers, true, false and null.

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

Would specifically quote what matches the specification of a json number and that is not already inside quotes.

Those do an exact tokenising based on the JSON specification, it's not an approximation.

Tags:

Shell

Json

Jq