基于另一个字段的值的条件元素的JSON路径索引

huangapple go评论74阅读模式
英文:

JSON path condifitional index of element based on value of another field

问题

{
  "array": [
    {
      "id": 1
    },
    {
      "id": 2
    }
  ],
  "conditionalField": "ab"
}

我希望根据$.conditionalField的值选择数组元素。我需要类似这样的表达式:

$.array[($.conditionalField == "ab" ? 0 : 1)]

JSON Path是否支持这样的操作?我使用的是Jayway JSON Path。

英文:

I want to select array element based on value of another object(not array part)

{
  "array": [
    {
      "id": 1
    },
    {
      "id": 2
    }
  ],
  "conditionalField": "ab"
}

I want select array element based on value of $.conditionalField. I need something like this:

$.array[($.conditionalField == "ab" ? 0 : 1)]

Does json path support this? I use Jayway JSON Path

答案1

得分: 1

抱歉,目前 JSONPath 无法实现此操作。通常情况下,当前的实现缺乏 XPath 1.0 的流畅性(更不用说 v2.0/3+)。

在像 XPath 1.0 这样不具备条件语句(if-else)功能的语言中,一种常见的技巧是使用一种叫做“Becker 方法”的技术来模拟条件语句。即将两个互斥的字符串拼接在一起,其中一个字符串根据条件变为空。在(XPath)伪代码中:

concat(
  substring('foo', 1, number(true) * string-length('foo')),
  substring('bar', 1, number(not(true)) * string-length('bar'))
)

我们可能可以在 JavaScript 中使用 JSON-Path 并利用脚本评估来实现类似的操作;我认为它应该是这样的(为了更好的可读性进行了分割):

$.[?(@.conditionalField && @.dict[0].id && @.dict[1].id && @.temp.concat( 
          @.dict[0].id.substring(0, @.conditionalField==='ab' * @.dict[0].id.length()) ) 
 .concat( @.dict[1].id.substring(0, @.conditionalField==='xy' * @.dict[1].id.length()) )
   )]

但是这并没有生效。因此,目前看来,在 JSON-Path 中直接模拟 if-else 构造似乎是不可能的。

一个实际的方法是分别选择这两个属性,并在主机环境中做出决策:

$.[?(@.conditionalField=='ab')].dict[0].id
$.[?(@.conditionalField=='xy')].dict[1].id
英文:

Unfortunately, this cannot be done in JSONPath as of now. Generally, current implementations lack the fluency of XPath 1.0 (let alone v2.0/3+).

A (well known) trick mimicking a conditional (if-else) in a language like XPath 1.0 that does not come with such a feature is to use a technique called "Becker's method", i.e. concatenating two mutually exclusive strings, where one of two strings becomes empty depending on a condition. In (XPath) pseudo-code:

concat(
  substring('foo', 1, number(true) * string-length('foo')),
  substring('bar', 1, number(not(true)) * string-length('bar'))
)

We might be able to do this using JSON-Path in JavaScript and leveraging script eval; I think it should look like this (slit-up for better readability):

$.[?(@.conditionalField && @.dict[0].id && @.dict[1].id && @.temp.concat( 
          @.dict[0].id.substring(0, @.conditionalField==='ab' * @.dict[0].id.length()) ) 
 .concat( @.dict[1].id.substring(0, @.conditionalField==='xy' * @.dict[1].id.length()) )
   )]

but it is not working. So, as of now, there seems to be no way to mimic an if-else construct in JSON-Path directly.

A practical approach is selecting both properties separately and make the decision in your host environment:

$.[?(@.conditionalField=='ab')].dict[0].id
$.[?(@.conditionalField=='xy')].dict[1].id

答案2

得分: 0

请尝试类似以下方式:

$。[?(@.conditionalField=="ab")].array [1] .id

输出应为:

[
   2
]
英文:

Try something like this:

$.[?(@.conditionalField=="ab")].array[1].id

Output should be:

[
   2
]

huangapple
  • 本文由 发表于 2020年9月24日 22:17:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/64048445.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定