Riempi tutti i numeri in JSON con le virgolette


11

Esistono dati JSON che contengono alcuni valori numerici. Come convertire tutte le cifre in stringhe? (avvolgere tra virgolette)

Esempio:

{
        "id":1,
        "customer":"user",
        "plate":"BMT-216-A",
        "country":"GB",
        "amount":1000,
        "pndNumber":20000,
        "zoneNumber":4
}

dovrebbe diventare

{
        "id":"1",
        "customer":"user",
        "plate":"BMT-216-A",
        "country":"GB",
        "amount":"1000",
        "pndNumber":"20000",
        "zoneNumber":"4"
}

Risposte:


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

Reindirizzare a un nuovo file e quindi spostarlo sul nome file originale.

Per una conversione più approfondita dei numeri in strutture non piane in stringhe, prendere in considerazione

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

Ciò esaminerebbe ogni valore ricorsivamente nel documento dato e selezionerebbe quelli che sono numeri. I valori selezionati vengono quindi convertiti in stringhe. Inoltre, a rigor di termini, esaminerebbe le chiavi, ma poiché questi non possono essere numeri semplici in JSON, nessuna chiave verrà selezionata.

Esempio:

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

Per citare ulteriormente il null, cambia select()in

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

3
Si noti che cambia {"a":{"b":1},"b":null}in{ "a": "{\"b\":1}", "b": "null" }
Stéphane Chazelas il

@ StéphaneChazelas Sì, trasformerebbe i sotto-oggetti in stringhe. La struttura di dati fornita non contiene tuttavia oggetti secondari.
Kusalananda

2
Non solo oggetti secondari, tutti i valori inclusi array, valori booleani e null(vale comunque la pena notare IMO anche se il campione dell'OP non ne ha nessuno).
Stéphane Chazelas,

E come cambiarlo se ho un array?
VK

@ StéphaneChazelas ordinati. Grazie per avermi preso in giro.
Kusalananda

8

ecco una soluzione semplice basata jtcsull'utilità 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 $ 

se ti piace applicare le modifiche direttamente nel file json, usa l' -fopzione, in questo modo:

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

La soluzione proposta funzionerà correttamente con un json strutturato arbitrario, ad esempio:

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 $ 
  • se ti piace citare valori null, basta lanciare un percorso -w'<>n:'
  • se ti piace citare valori booleani, lancia un percorso -w'<any>b:'

Inoltre, l'attività inversa (annulla tutte le cifre) viene facilmente eseguita nello stesso modo: diciamo, file.jsonè già "enquotata", per annullare la citazione di tutte le cifre:

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 $ 

AGGIORNAMENTO : l'ultima versione di jtcimplementa ora modelli e spazi dei nomi. Con ciò non è richiesta alcuna chiamata alla shell esterna:

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

jtcguida per l'utente: https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md


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

Citarebbe tutto ciò che non è citato e non lo è []{}:,whitespace, così citerebbe i numeri true, falsee null.

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

Citarebbe specificamente ciò che corrisponde alla specifica di un numero json e che non è già tra virgolette.

Quelli fanno un tokenising esatto basato sulla specifica JSON, non è un'approssimazione.


-1

Ho provato con il metodo seguente e ha funzionato bene.

Ho pipeline 2 volte provato fino al mio livello per ridurlo

Comando:

sed 's/[0-9]\{1,\},\?$/"&/g' filename |
sed '/[0-9]\{1,\}$/s/[0-9]\{1,\}/&"/g'|
sed '/[0-9]\{1,\},$/s/,$/"&/g`'

Produzione:

 {
        "id":"1",
        "customer":"user",
        "plate":"BMT-216-A",
        "country":"GB",
        "amount":"1000",
        "pndNumber":"20000",
        "zoneNumber":"4"
}

@Kusalananda ha corretto il codice
Praveen Kumar BS

perchè usi \{1,\},? Per verificare se un elemento appare una o più volte utilizzare +. E questo non funzionerà con numeri come -123, 0xab, 0o12, 0b1011, 1e23 o 1.2e3 ...
phuclv

@phuclv \{1,\}è l'equivalente BRE di ERE +. Alcune sedimplementazioni supportano \+come estensione o opzione -Eo -rper abilitare ERE ma non è portatile. \?è un'altra estensione non portatile sebbene il cui equivalente standard sia\{0,1\}
Stéphane Chazelas il

@phuclv non troverai numeri 0xab 0o12 0b1011 non quotati in un file JSON valido.
Stéphane Chazelas,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.