Json 标记jq如何将多个路径组合到一个对象中

Json 标记jq如何将多个路径组合到一个对象中,json,object,filtering,jq,Json,Object,Filtering,Jq,我有一个对象,我可以过滤到几个我希望保留的路径。路径的形式如下: [ "key1", "key2", "mykey" ] [ "key3", "key4", "mykey" ] 我想要的是: { "key1":{ "key2": .key2 }, "key3":{ "key4": .key4 } } 我能得到的最接近的结果是: { "key1":{ "key2": .key2 } } { "k

我有一个对象,我可以过滤到几个我希望保留的路径。路径的形式如下:

[
  "key1",
  "key2",
  "mykey"
]
[
  "key3",
  "key4",
  "mykey"
]
我想要的是:

{ "key1":{
      "key2": .key2
       },
  "key3":{
      "key4": .key4
       }
}
我能得到的最接近的结果是:

{ "key1":{
   "key2": .key2
      }
}
{  "key3":{
      "key4": .key4
}
使用:

(paths(objects)|select(last(.[])=="mykey")) as $path|
getpath([$path[0],$path[1]]) as $getpath|
{($path[0]):{($path[1]):$getpath}}
虽然我可以通过管道将此输出传输到jq-s'.'命令,但我找不到一种方法将原始过滤器集中的路径重建相加。过滤器似乎在每个对象的末尾重置$path看起来一次只保存一个路径数组,而不是一个路径数组。这防止我在reduce函数中迭代$path

我已经创建了下面的脚本,但我对如何使用path()函数感兴趣。到目前为止,我还没有弄明白如何使它对我非常有用

(to_entries |
 map(select(.["value"][]?|has("mykey")?))|[.[].key]) as $rooms|
(to_entries |
 map(select(.["value"][]?|has("mykey")?))|[.[].value]) as $roomvals| #allows room paths to be avail

##### creates object containing only those locations and sensors within the locations that include "mykey" objs

reduce
range(0;$rooms|length) as $i ({};
.+{($rooms[$i]): ($roomvals[$i] | to_entries |
map(select(.["value"]|has("mykey")))|{(.[]["key"]):.[]["value"]})})

感谢您对这些方法的任何帮助或其他方法的建议。

您表示想要的输出不是JSON,我也不清楚想要的输出是什么,但以下内容似乎很接近:

reduce inputs as $d (null; setpath( $d[0: ($d|length) - 1]; $d[-1] ) )
通过您的输入,并使用jq-n,这将产生:

{
  "key1": {
    "key2": "mykey"
  },
  "key3": {
    "key4": "mykey"
  }
}
希望你能从这里开始

例子: 调用:jq-n-c-f example.jq

输出:

{"key1":{"key2":{"mykey":{"a":123}}},
 "key3":{"key4":{"mykey":{"b":234}}}}

在peak回答的指导下,我现在可以更好地摆姿势回答我的问题

我已经扩展了peak在其示例中使用的数据对象,因此它更好地代表了我试图解决的问题。现在数据更好地说明了“键2”和“键10”有“mykey”,而“键6”、“键8”和“键11”没有。我想在我的问题中表达的是,我想保留“key2”和“key10”的完整路径,其中包括“另一个”和“我的键”。我意识到对peak的示例选择标准进行一个小小的修改就可以做到这一点。我只需要在选择中添加一个过滤器,以保留包含“mykey”的每个路径的前两个元素:

返回我想要的:

{"key1":{"key2":{"mykey":{"a":123},
                 "another":{"q":"six"}}},
 "key3":{"key6":{"mykey":{"d":997},
                 "another":{"q":"seven"}}}
}
您将注意到选择现在包括“|[0:2]”


感谢peak将我的工作安排在正确的轨道上。我投票支持他的答案,因为它帮助我更好地表达我的问题,并让我有解决问题的洞察力。

作为JSON新手,我可能没有选择正确的方式来说明我想要什么。主要对象“key1”和“key3”都有子对象,而子对象又有一个“mykey”。没有说明的是,“mykey”只是对象“key2”和“key4”的几个子对象之一。{“key2”:.key2}可能最好用另一种方式表示,比如说
{“key2”:getpath(“key2”)}
。顺便说一句,我找不到data“你在jq手册中使用的关键字。它是做什么的?”“data”应该在这里是“inputs”。你想产生JSON输出吗?
def data: 
  { "key1": { "key2": {"mykey": {"a": 123},
                       "another":{"q": "six"} },
              "key6": {"key7": {"d": 997} } },
    "key3": { "key8": {"key9": {"b": 234} },
              "key10": {"mykey": {"d": 997},
                       "another":{"q": "seven"} } },
    "key4": { "key11": {"key5" : {"a": 123} } }
  };

def selection(mykey):

  . as $in 
  | reduce (paths(objects) | select(last(.[])==mykey)|.[0:2]) as $path
      (null; setpath($path; $in|getpath($path)) );

data | selection("mykey")
{"key1":{"key2":{"mykey":{"a":123},
                 "another":{"q":"six"}}},
 "key3":{"key6":{"mykey":{"d":997},
                 "another":{"q":"seven"}}}
}