如何在JSONPath中根据数组中对象的内容进行过滤?

人工智能 2026-07-07

我正在尝试创建一个JSONPath(RFC 9525)表达式,用来根据未命名的JSON对象内部字段来过滤结果,正如花括号 {} 所示。在这种情况下,数组条目是 udm=="50"

我的JSON数据如下所示:

{
  "0": [
    [
      "Why are we here",
      {
        "zi": "AI Mode",
        "zf": 27,
        "zp": {
          "udm": "50"
        }
      }
    ],
    [
      "world cup standing",
      {
        "zf": 27
      }
    ],
    [
      "test",
      {
        "zf": 27,
        "zp": {
          "udm": "2"
        },
        "zi": "Images"
      }
    ]
  ]
}

并且我想要的结果看起来像这样:

[
  "Why are we here",
  {
    "zi": "AI Mode",
    "zf": 27,
    "zp": {
      "udm": "50"
    }
  }
]

我尝试过的方法:

如果我排除过滤条件,就能选到正确的数据层级。

$["0"][*][*]
[
  "Why are we here",
  {
    "zi": "AI Mode",
    "zf": 27,
    "zp": {
      "udm": "50"
    }
  },
  "world cup standing",
  {
    "zf": 27
  },
  "test",
  {
    "zf": 27,
    "zp": {
      "udm": "2"
    },
    "zi": "Images"
  }
]

我可以过滤JSON对象内部的数据,但它不会让我获得对象外部的数据。

$..[[email protected]=="50"]
[
  {
    "zi": "AI Mode",
    "zf": 27,
    "zp": {
      "udm": "50"
    }
  }
]

我以为可以在过滤器中使用像 *.. 这样的通配符来表示JSON对象,但 JSONPath Evaluator 给出语法错误。

$..[?@*.zp.udm=="50"]
$..[?@[*].zp.udm=="50"]
$..[?@.*.zp.udm=="50"]
$..[[email protected]=="50"]

如何编写一个JSONPath表达式,在过滤未命名对象内部的数据的同时返回未命名对象外部的数据?

编辑:为便于理解,我正在为Google的 AI相关自动完成建议,以及 uBlock Origin 与AdGuard制作一个过滤器,它们使用的是修改版本的JSONPath。它们的语法基于RFC 9525,但并非完全等同于它。为了保留当前答案,我将保持问题的原文。

解决方案

这确实有点棘手,在线评估器的输出也可能产生误导。你需要记住以下几点:

  • JSONPath查询总是返回一个 匹配项列表,即使只有一个匹配。

这意味着如果没有匹配项(结果为空),它会给你 []。如果只有一个匹配项,则以 [1st-match] 返回,依此类推。

因此,如果你应用这个JSONPath表达式 $["0"],去获取与键 "0" 相关联的值,你得到的结果如下:

[
  [
    [
      "Why are we here",
      {
        "zi": "AI Mode",
        "zf": 27,
        "zp": {
          "udm": "50"
        }
      }
    ],
    [
      "world cup standing",
      {
        "zf": 27
      }
    ],
    [
      "test",
      {
        "zf": 27,
        "zp": {
          "udm": "2"
        },
        "zi": "Images"
      }
    ]
  ]
]

请注意,评估器会额外添加最外层的一对括号 [...],因为这是前文所述的标准做法。它不是来自你原始文档的。

你想要在这条路径上进一步向下导航,找到一个子元素,使得:

  • 需要匹配具有某种元素模式的子元素,这可以通过过滤运算符 ? 实现
  • 每个子元素都是一个数组,表示为 @,作为“当前数组元素”
  • 在该当前数组元素的第二个子元素(基于从0 开始)也就是 @[1] 上,我希望匹配的子元素具有一个键,其键名为 zp,该键对应的值再包含一个键名为 udm 的值,其值为 "50"。因此:[?@[1].zp.udm=="50"]
  • 把它追加到前面的结果上,我们得到:$["0"][?@[1].zp.udm=="50"]

我们得到的结果如下:

[
  [
    "Why are we here",
    {
      "zi": "AI Mode",
      "zf": 27,
      "zp": {
        "udm": "50"
      }
    }
  ]
]

就JSONPath表达式能做到的程度而言,我们已经达到目标,但评测器会再次自动添加一对额外的括号 [...],不过这并不是实际数据本身。调用该结果的程序(无论用JavaScript、C#还是其他语言编写)有责任检查结果,并查看结果列表中是否至少有一个元素。如果没有,则表示没有匹配项;如果有,则在你自己的代码中获取列表中的第一个元素。你将得到如下结果:

[
  "Why are we here",
  {
    "zi": "AI Mode",
    "zf": 27,
    "zp": {
      "udm": "50"
    }
  }
]

这正是你想要的。

总结

  • JSONPath表达式:$["0"][?@[1].zp.udm=="50"]
  • 程序应检查结果列表的长度
  • 如果长度 > 0,则将其第一个元素作为实际结果
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章