web-dev-qa-db-ja.com

条件または最初の値のみで配列から値を取得するJSONPath式

このように構造化された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]"
      }
   ]
}

JSONPath式 にステータスVERIFIEDfirstメールを取得し、ない場合は、次に、配列の最初のメールを取得します。したがって、上記の例の場合、結果は[email protected]。この例を考えると:

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

結果は[email protected]

これはJSONPath式で可能ですか?

7
jhericks

実際には2つのJSONPath式があり、2番目の式(最初の電子メール)は最初の式(最初の検証済み電子メール)が何も返さない場合にのみ評価する必要があるため、1つで両方を同時に評価することはできないと思います式。

ただし、次々に適用できます。

_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");
}
_

電子メール配列が空の場合、 option _SUPPRESS_EXCEPTIONS_のおかげで、ctx.read("$.emails[0].email")は例外をスローする代わりにnullを返します。


パスの数が事前にわからない場合:

_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;
}
_

オプション _ALWAYS_RETURN_LIST_は、結果が1つまたは0の場合でも、戻り値の型がリストであることを意味します。

11
approxiblue

このコードはあなたのために完全に機能するはずです

//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);
0
user8715994