JSONPath 表达式以根据条件从数组中获取值或仅获取第一个值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41471244/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 18:45:53  来源:igfitidea点击:

JSONPath expression to get a value from an array on condition or just the first value

jsonjsonpath

提问by jhericks

Given JSON structured like this:

鉴于 JSON 结构如下:

{
   "name":"Some Guy",
   "emails":[
      {
         "description":"primary",
         "status":"UNVERIFIED",
         "email":"[email protected]"
      },
      {
         "description":"home",
         "status":"VERIFIED",
         "email":"[email protected]"
      },
      {
         "description":"away",
         "status":"VERIFIED",
         "email":"[email protected]"
      }
   ]
}

I would like a JSONPath expressionto get the firstemail with status VERIFIEDand if there are none, then just get the first email in the array. So, given the example above, the result would be [email protected]. Given this example:

我想要一个JSONPath 表达式来获取第一封带有状态的电子邮件,VERIFIED如果没有,那么只获取数组中的第一封电子邮件。因此,鉴于上面的示例,结果将是[email protected]。鉴于这个例子:

{
   "name":"Some Guy",
   "emails":[
      {
         "description":"primary",
         "status":"UNVERIFIED",
         "email":"[email protected]"
      },
      {
         "description":"home",
         "status":"UNVERIFIED",
         "email":"[email protected]"
      }
   ]
}

the result would be [email protected].

结果是[email protected]

Is this possible with a JSONPath expression?

这可以用 JSONPath 表达式实现吗?

回答by approxiblue

You effectively have 2 JSONPath expressions, where the second one (first email) should be evaluated only if the first one (first verified email) returns nothing, so I don't think you can evaluate them both at the same time, in a single expression.

您实际上有 2 个 JSONPath 表达式,其中第二个(第一封电子邮件)仅在第一个(第一个经过验证的电子邮件)不返回任何内容时才应进行评估,因此我认为您不能同时对它们进行一次评估表达。

You can apply them one after the other, though:

不过,您可以一个接一个地应用它们:

public static String getEmail(String json) {
    Configuration cf = Configuration.builder().options(Option.SUPPRESS_EXCEPTIONS).build();
    DocumentContext ctx = JsonPath.using(cf).parse(json);
    List<String> emails = ctx.read("$.emails[?(@.status == 'VERIFIED')].email");
    if (!emails.isEmpty()) {
        return emails.get(0);
    }
    return ctx.read("$.emails[0].email");
}

If the email array is empty, ctx.read("$.emails[0].email")will return null instead of throwing an exception, thanks to the optionSUPPRESS_EXCEPTIONS.

如果 email 数组为空,ctx.read("$.emails[0].email")将返回 null 而不是抛出异常,这要归功于optionSUPPRESS_EXCEPTIONS



If you don't know the number of paths in advance:

如果您事先不知道路径数:

public static String getEmail(String json, String[] paths) {
    Configuration cf = Configuration.builder().options(Option.ALWAYS_RETURN_LIST, Option.SUPPRESS_EXCEPTIONS).build();
    DocumentContext ctx = JsonPath.using(cf).parse(json);
    for (String path : paths) {
        List<String> emails = ctx.read(path);
        if (!emails.isEmpty()) {
            return emails.get(0);
        }
    }
    return null;
}

The optionALWAYS_RETURN_LISTmeans the return type is a list, even when you have one or zero results.

选项ALWAYS_RETURN_LIST意味着返回类型是一个列表,即使您有一个或零个结果。

回答by jhericks

This code should work perfectly for you

此代码应该非常适合您

//Use the json parsing library to extract the data
    JsonPath jp = new JsonPath(json); 
    Map<String, Object> location = jp.get("name.emails[0]");
    System.out.println(location);