使用jq将json嵌套键值对向上移动一级

时间:2017-09-29 21:20:35

标签: json geojson jq

我想使用jq移动嵌套键:值对齐一个级别。因此给出了像这样的geojson对象数组:

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

我想返回完全相同的对象,但在"group": "car"对象中使用features。所以结果看起来像这样:

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

这看起来很简单,但不知怎的,我正在努力弄清楚如何用jq做到这一点。帮助赞赏!

4 个答案:

答案 0 :(得分:0)

jq 解决方案:

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

输出:

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

答案 1 :(得分:0)

分两步(先添加,然后删除):

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

或者更简洁:

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

答案 2 :(得分:0)

问题并没有讨论如果没有活动或应该做什么 如果有多个活动,则以下过滤器封装 属性更改为函数:

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

 .features[].properties |= update_activity
如果没有其他活动,

.properties将保持不变 第一个活动被移动到该属性,其他活动未经修改。 因此,如果样本输入(稍微缩写)是

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

结果将是

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

这种方法提供了一个特定的地方来处理逻辑处理其他 变化。例如。此版本的update_activity将删除.group 所有活动:

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

如果没有活动,此版本也会将.group指定为null:

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

答案 3 :(得分:0)

这是一个通用的解决方案:

# 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)
;

通过这个定义,解决方案很简单:

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