Wrap all numerics in JSON with quotes
Solution 1
$ 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")
Solution 2
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
Solution 3
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.
Related videos on Youtube
Comments
-
V-K over 1 year
There are JSON data which contains some numeric values. How to convert all numerics to strings? (wrap with quotes)
Example:
{ "id":1, "customer":"user", "plate":"BMT-216-A", "country":"GB", "amount":1000, "pndNumber":20000, "zoneNumber":4 }
should become
{ "id":"1", "customer":"user", "plate":"BMT-216-A", "country":"GB", "amount":"1000", "pndNumber":"20000", "zoneNumber":"4" }
-
Stéphane Chazelas about 5 yearsNote that it changes
{"a":{"b":1},"b":null}
to{ "a": "{\"b\":1}", "b": "null" }
-
Kusalananda about 5 years@StéphaneChazelas Yes, it would turn sub-objects into strings. The given data structure does not however contains sub-objects.
-
Stéphane Chazelas about 5 yearsNot only sub-objects, all values including arrays, booleans and
null
(still worth noting IMO even though the OP's sample has none of those). -
Kusalananda about 5 years@StéphaneChazelas Sorted. Thanks for poking at me.
-
Praveen Kumar BS about 5 years@Kusalananda corrected the code
-
phuclv about 5 yearswhy do you use
\{1,\},
? To test whether an element appears one or more times use+
. And this won't work for numbers like -123, 0xab, 0o12, 0b1011, 1e23 or 1.2e3... -
Stéphane Chazelas about 5 years@phuclv
\{1,\}
is the BRE equivalent of ERE+
. Somesed
implementations support\+
as an extension or a-E
or-r
option to enable EREs but that's not portable.\?
is another non-portable extension though whose standard equivalent is\{0,1\}
-
Stéphane Chazelas about 5 years@phuclv you wouldn't find unquoted 0xab 0o12 0b1011 numbers in a valid JSON file.