【问题标题】:get full path up to given element获取到给定元素的完整路径
【发布时间】:2021-11-01 18:30:42
【问题描述】:

我已经从 Firefox 中导出了书签,在我的例子中是安静的大型 JSON。我对带有 guid _0no-4e9woLW 的 JSON 对象感兴趣,例如这个:

{
  "foo": {
    "bar": {
      "zoo": {
        "guid": "_0no-4e9woLW",
        "title": "frontend",
        "index": 3,
        "dateAdded": 1614198626454000,
        "lastModified": 1619505016472000,
        "id": 16518,
        "typeCode": 2,
        "type": "text/x-moz-place-container",
        "children": [
          {
            "guid": "2L7ZsYTM2RX0",
            "title": "css child override parent style",
            "index": 0,
            "dateAdded": 1614198648005000,
            "lastModified": 1614198648005000,
            "id": 16519,
            "typeCode": 1,
            "type": "text/x-moz-place",
            "uri": "https://www.google.com/search?client=firefox-b-d&q=css+child+override+parent+style"
          },
          {
            "guid": "x3JHTAezzyI8",
            "title": "css child parent inheritance",
            "index": 1,
            "dateAdded": 1614198648096000,
            "lastModified": 1614198648096000,
            "id": 16520,
            "typeCode": 1,
            "type": "text/x-moz-place",
            "uri": "https://www.google.com/search?client=firefox-b-d&q=css+child+parent+inheritance"
          }
        ]
      }
    }
  }
}

是否有可能以某种方式获得到"guid": "_0no-4e9woLW" 的完整路径? guid 键在 JSON 中是唯一的。我的目标是输入类似jq '["full path I've somehow previously obtained"]["children"].title'

我会得到:

css child override parent style
css child parent inheritance

我当然可以手动执行此操作,但我太懒了。

【问题讨论】:

  • 您在询问full path up to "guid",但尚未显示您的 JSON 结构。我们如何确定guid 存在于哪个路径下?

标签: json jq


【解决方案1】:

如果没有 JSON 的全部知识,当使用 path 系列函数(即 getpath/1)时,这样的事情应该可以工作

( paths | select(.[-1] == "guid") ) as $p | 
  if getpath($p)  == "_0no-4e9woLW" then getpath($p[:-1] + ["children"])[].title else empty end

上面的构造意味着,选择所有包含名为guid 的叶键的路径并将它们存储在一个变量中,并仅过滤其值为"_0no-4e9woLW" 的路径。在选定的路径上,修剪子节点($p[:-1] 删除"guid")并添加节点"children" 并获取构造的新路径的值(使用getpath/1)。从 JSON 值中提取 .title 字段

jqplay demo

【讨论】:

    【解决方案2】:

    使用recurse 可以轻松到达对象:

    jq -r 'recurse |
           select(type=="object" and .guid == "_0no-4e9woLW")
           .children[].title' firefox.json
    

    【讨论】:

    • 这只是通过 guid 查找对象,这不是所要求的。但如果这是需要的话,你只需要.. | objects | select(.guid == "_0no-4e9woLW") | .title
    • @ikegami 如果您尝试过我的解决方案,您会看到它输出的正是 OP 想要的。你的只给出一个值null
    • Re "你会看到它输出的正是 OP 想要的。",哦,我知道。或者我假设那么多。我只是说它太复杂了。 /// Re "Yours 只给出一个值 null.", Not true
    • 对不起,由于我构建的测试数据,我得到了 null。无论如何,你的没有得到 OP 的预期。我不同意我的解决方案过于复杂。
    • 这不是主观的。 select(type=="object") 客观上比objects 更复杂。它有 1/3 的表达式,唯一的表达式是微不足道的 /// .children[].title, whateves。
    【解决方案3】:
    • 通过 guid 访问节点:

      .. | objects | select( .guid == … )
      

      因此,您将使用以下内容来获取 _0no-4e9woLW 的孩子的标题:

      .. | objects | select( .guid == "_0no-4e9woLW" ) | .children[].title
      

      Demo on jqplay

    • 保存路径:

      path( … )               # As JSON
      
      path( … ) | join(".")   # As dotted path
      

      替换为返回您想要其路径的节点的表达式。

      例如,

      path( .. | objects | select( .guid == "_0no-4e9woLW" ) )   # [ "foo", "bar", "zoo" ]
      

      Demo on jqplay

      path( .. | objects | select( .guid == "_0no-4e9woLW" ) ) | join(".")   # "foo.bar.zoo"
      

      Demo on jqplay

    • 使用路径抓取对象:

      getpath( … )                                      # From JSON
      
      getpath( … | split(".") | map(tonumber? // .) )   # From dotted path
      

      替换为返回先前保存路径的表达式。

      例如,

      getpath( [ "foo", "bar", "zoo" ] ).children[].title
      

      Demo on jqplay

      getpath( "foo.bar.zoo" | split(".") | map(tonumber? // .) ).children[].title
      

      Demo on jqplay

    【讨论】:

    • 我猜这里有些逻辑被打破了。我试过path( .. | objects | .guid == "_0no-4e9woLW" ),但它返回jq: error (at <stdin>:39): Invalid path expression with result false exit status 5,如果我改为path( .. | objects ),那么我会得到一些输出,但不是想要的。 jqplay.org/s/ijCi1e_r66
    • 应该是path( .. | objects | select(.guid == "_0no-4e9woLW") )。调整后的答案。
    • 现在这个不行了path( .. | objects | select( .guid == "_0no-4e9woLW" ) ) | join(".")
    • 不是这样。 It does work
    【解决方案4】:
    json2jqpath.jq file.json 
    .
    .foo
    .foo|.bar
    .foo|.bar|.zoo
    .foo|.bar|.zoo|.children
    .foo|.bar|.zoo|.children|.[]
    .foo|.bar|.zoo|.children|.[]|.dateAdded
    .foo|.bar|.zoo|.children|.[]|.guid
    .foo|.bar|.zoo|.children|.[]|.id
    .foo|.bar|.zoo|.children|.[]|.index
    .foo|.bar|.zoo|.children|.[]|.lastModified
    .foo|.bar|.zoo|.children|.[]|.title
    .foo|.bar|.zoo|.children|.[]|.type
    .foo|.bar|.zoo|.children|.[]|.typeCode
    .foo|.bar|.zoo|.children|.[]|.uri
    .foo|.bar|.zoo|.dateAdded
    .foo|.bar|.zoo|.guid
    .foo|.bar|.zoo|.id
    .foo|.bar|.zoo|.index
    .foo|.bar|.zoo|.lastModified
    .foo|.bar|.zoo|.title
    .foo|.bar|.zoo|.type
    .foo|.bar|.zoo|.typeCode
    

    显示guid 在多个唯一路径中显示为叶子。 如果只有一个你就完蛋了 (假设您知道该值存在) 使用多个路径,您需要检查该值是否存在 它是您感兴趣的对象。

    json2jqpath.jq file.json | grep guid
    .foo|.bar|.zoo|.children|.[]|.guid
    .foo|.bar|.zoo|.guid
    

    将给定值附加到路径会返回包含它们的对象

    jq '.foo|.bar|.zoo|.children|.[]|.guid="_0no-4e9woLW"' file.json 
    {
      "guid": "_0no-4e9woLW",
      "title": "css child override parent style",
      "index": 0,
      "dateAdded": 1614198648005000,
      "lastModified": 1614198648005000,
      "id": 16519,
      "typeCode": 1,
      "type": "text/x-moz-place",
      "uri": "https://www.google.com/search?client=firefox-b-d&q=css+child+override+parent+style"
    }
    {
      "guid": "_0no-4e9woLW",
      "title": "css child parent inheritance",
      "index": 1,
      "dateAdded": 1614198648096000,
      "lastModified": 1614198648096000,
      "id": 16520,
      "typeCode": 1,
      "type": "text/x-moz-place",
      "uri": "https://www.google.com/search?client=firefox-b-d&q=css+child+parent+inheritance"
    }
    
    
    jq '.foo|.bar|.zoo|.guid="_0no-4e9woLW"' file.json 
    {
      "guid": "_0no-4e9woLW",
      "title": "frontend",
      "index": 3,
      "dateAdded": 1614198626454000,
      "lastModified": 1619505016472000,
      "id": 16518,
      "typeCode": 2,
      "type": "text/x-moz-place-container",
      "children": [
        {
          "guid": "2L7ZsYTM2RX0",
          "title": "css child override parent style",
          "index": 0,
          "dateAdded": 1614198648005000,
          "lastModified": 1614198648005000,
          "id": 16519,
          "typeCode": 1,
          "type": "text/x-moz-place",
          "uri": "https://www.google.com/search?client=firefox-b-d&q=css+child+override+parent+style"
        },
        {
          "guid": "x3JHTAezzyI8",
          "title": "css child parent inheritance",
          "index": 1,
          "dateAdded": 1614198648096000,
          "lastModified": 1614198648096000,
          "id": 16520,
          "typeCode": 1,
          "type": "text/x-moz-place",
          "uri": "https://www.google.com/search?client=firefox-b-d&q=css+child+parent+inheritance"
        }
      ]
    }
    

    json2jqpath.jq

    【讨论】:

      猜你喜欢
      • 2016-08-19
      • 2018-04-09
      • 1970-01-01
      • 2017-03-16
      • 2014-12-14
      • 2019-11-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多