2015-05-21 9 views
5

Ambiente: JQ 1.5, Windows 64-bit.Elaborazione JSON di array in array con j

Ho il seguente JSON:

{ 
    "unique": 1924, 
    "coordinates": [ 
    { 
     "time": "2015-01-25T00:00:01.683", 
     "xyz": [ 
     { 
      "z": 4, 
      "y": 2, 
      "x": 1, 
      "id": 99 
     }, 
     { 
      "z": 9, 
      "y": 9, 
      "x": 8, 
      "id": 100 
     }, 
     { 
      "z": 9, 
      "y": 6, 
      "x": 10, 
      "id": 101 
     } 
     ] 
    }, 
    { 
     "time": "2015-01-25T00:00:02.790", 
     "xyz": [ 
     { 
      "z": 0, 
      "y": 3, 
      "x": 7, 
      "id": 99 
     }, 
     { 
      "z": 4, 
      "y": 6, 
      "x": 2, 
      "id": 100 
     }, 
     { 
      "z": 2, 
      "y": 9, 
      "x": 51, 
      "id": 101 
     } 
     ] 
    } 
    ] 
} 

E vorrei convertirlo in questo formato CSV con JQ:

unique,time,id,x,y,z 
1924,"2015-01-25T00:00:01.683",99,1,2,4 
1924,"2015-01-25T00:00:01.683",100,8,9,9 

(e così via)

Ho provato alcuni cose, come ad esempio:

jq -r '{unique: .unique, coordinates: .coordinates[].xyz[] | [.id, .x, .y, .z], time: .coordinates.[].time} | flatten | @csv' 

che mi ha dato il JSON desiderato, ma moltiplicato per ogni id, x, y e z (ad es. ogni linea unica appare quattro volte, una per id, x, y, z).

Assegnazione di un numero alla matrice, come ad esempio

jq -r '{unique: .unique, coordinates: .coordinates[0].xyz[] | [.id, .x, .y, .z], time: .coordinates.[0].time} | flatten | @csv' 

mi dà il primo indice della matrice coordinates, ma mi piacerebbe tutti loro, naturalmente.

+0

Per quale lingua? Javascript? –

+2

Con jq (http://stedolan.github.io/jq/) – innocentunremarkable

+0

Mmm. Richiedere una build molto recente, lì; Sono ancora in 1.4. Ma allora, questo è il modo in cui le caratteristiche brillanti ... –

risposta

5

Il primo passo sarebbe quello di appiattire i risultati in righe.

[{ unique } + (.coordinates[] | { time } + .xyz[])] 

Ciò produrrà un array di oggetti per riga:

[ 
    { 
    "unique": 1924, 
    "time": "2015-01-25T00:00:01.683", 
    "id": 99, 
    "x": 1, 
    "y": 2, 
    "z": 4 
    }, 
    { 
    "unique": 1924, 
    "time": "2015-01-25T00:00:01.683", 
    "id": 100, 
    "x": 8, 
    "y": 9, 
    "z": 9 
    }, 
    { 
    "unique": 1924, 
    "time": "2015-01-25T00:00:01.683", 
    "id": 101, 
    "x": 10, 
    "y": 6, 
    "z": 9 
    }, 
    { 
    "unique": 1924, 
    "time": "2015-01-25T00:00:02.790", 
    "id": 99, 
    "x": 7, 
    "y": 3, 
    "z": 0 
    }, 
    ... 
] 

Poi è solo una questione di convertire questo file csv.

["unique","time","id","x","y","z"] as $fields | $fields, (.[] | [.[$fields[]]]) | @csv 
+0

p.s., questo dovrebbe funzionare anche per il 1.4. –

+0

Grazie! Sto usando il paradigma flatten/@csv per i comandi precedenti - diresti che il tuo metodo di conversione in CSV è più veloce/più efficiente? – innocentunremarkable

+0

Non penso che "flatten" funzionerebbe davvero qui. Ha lo scopo di appiattire array di matrici, non oggetti. E non vorresti usarlo perché l'appiattimento di un oggetto produrrà i valori. Perderai le chiavi associate e l'ordine non è garantito. Dovresti convertire in altre forme intermedie per usarlo meglio. L'approccio che ho seguito è più diretto, quindi mi aspetto che sia relativamente più veloce di cercare di farlo funzionare con il flatten. –