2017-09-29 3 views
0

Je souhaite utiliser jq pour déplacer une clé imbriquée: la paire de valeurs monte d'un niveau. Donc, étant donné un tableau de GeoJSON d'objets comme celui-ci:Déplacement d'une paire valeur/clé imbriquée json d'un niveau avec jq

{ 
     "type" : "FeatureCollection", 
     "features" : [ { 
     "type" : "Feature", 
     "geometry" : { 
      "type" : "MultiLineString", 
      "coordinates" : [ [ [ -74, 40 ], [ -73, 40 ] ] ] 
     }, 
     "properties" : { 
      "startTime" : "20160123T162547-0500", 
      "endTime" : "20160123T164227-0500", 
      "activities" : [ { 
      "activity" : "car", 
      "group" : "car" 
      } ] 
     } 
     } ] 
    } 

Je veux retourner exactement le même objet, mais avec "group": "car" dans l'objet features. Ainsi, le résultat ressemblerait à quelque chose comme ceci:

{ 
     "type" : "FeatureCollection", 
     "features" : [ { 
     "type" : "Feature", 
     "geometry" : { 
      "type" : "MultiLineString", 
      "coordinates" : [ [ [ -74, 40 ], [ -73, 40 ] ] ] 
     }, 
     "properties" : { 
      "type" : "move", 
      "startTime" : "20160123T162547-0500", 
      "endTime" : "20160123T164227-0500", 
      "group" : "car", 
      "activities" : [ { 
      "activity" : "car" 
      } ] 
     } 
     } ] 
    } 

Cela semble simple, mais en quelque sorte j'ai du mal à comprendre comment le faire avec JQ. Aide appréciée!

+0

bienvenue à SO. Qu'avez-vous essayé jusqu'à présent? – bated

Répondre

0

solution JQ:

jq '(.features[0].properties.group = .features[0].properties.activities[0].group) 
| del(.features[0].properties.activities[0].group)' input.json 

La sortie:

{ 
    "type": "FeatureCollection", 
    "features": [ 
    { 
     "type": "Feature", 
     "geometry": { 
     "type": "MultiLineString", 
     "coordinates": [ 
      [ 
      [ 
       -74, 
       40 
      ], 
      [ 
       -73, 
       40 
      ] 
      ] 
     ] 
     }, 
     "properties": { 
     "startTime": "20160123T162547-0500", 
     "endTime": "20160123T164227-0500", 
     "activities": [ 
      { 
      "activity": "car" 
      } 
     ], 
     "group": "car" 
     } 
    } 
    ] 
} 
0

En deux étapes (d'abord ajouter, puis supprimez):

.features[0].properties |= (.group = .activities[0].group) 
| del(.features[0].properties.activities[0].group) 

Ou encore plus succinctement:

.features[0].properties |= 
    ((.group = .activities[0].group) | del(.activities[0].group)) 
+0

cette réponse est également correcte, mais la précédente était juste un peu plus complète. –

0

Le problème ne discute pas ce qu'il faut faire s'il n'y a aucune activité ou s'il y a plus d'une activité si le filtre suivant encapsule le changement de propriété à une fonction:

def update_activity: 
    if .activities|length<1 then . 
    else 
     .group = .activities[0].group 
     | del(.activities[0].group) 
    end 
; 

.features[].properties |= update_activity 

.properties est laissé non modifié lorsqu'il n'y a pas d'activités sinon le groupe de la première activité est déplacé vers la propriété, laissant les autres activités non modifiées. Donc, si l'entrée de l'échantillon (un peu abrégé) étaient à la place

{ 
    "type" : "FeatureCollection", 
    "features" : [ { 
    "properties" : { 
     "activities" : [ { 
     "activity" : "car", 
     "group" : "car" 
     }, { 
     "activity" : "bike", 
     "group" : "bike" 
     } ] 
    } 
    } ] 
} 

le résultat serait

{ 
    "type": "FeatureCollection", 
    "features" : [ { 
    "properties" : { 
     "group": "car", 
     "activities": [ { 
      "activity": "car" 
     }, { 
      "activity": "bike", 
      "group": "bike" 
     } ] 
    } 
    } ] 
} 

Cette approche offre un lieu spécifique pour mettre la logique face à d'autres variations. Par exemple. cette version de update_activity supprime les .group de toutes les activités:

def update_activity: 
    if .activities|length<1 then . 
    else 
     .group = .activities[0].group 
     | del(.activities[].group) 
    end 
; 

et cette version attribue également .group null dans le cas où il n'y a pas de loisir:

def update_activity: 
    if .activities|length<1 then 
     .group = null 
    else 
     .group = .activities[0].group 
     | del(.activities[].group) 
    end 
; 
0

Voici une solution généralisée:

# move the key/value specified by apath up to the containing JSON object: 
def up(apath): 
    def trim: 
    if .[-1] | type == "number" then .[0:-2] | trim 
    else . 
    end; 

. as $in 
| (null | path(apath)) as $p 
| ($p|last) as $last 
| $in 
| getpath($p) as $v 
| setpath(($p[0:-1]|trim) + [$last]; $v) 
| del(apath) 
; 

Avec cette définition, la solution est simplement:

up(.features[0].properties.activities[0].group)