web-dev-qa-db-fra.com

Expression JSONPath pour obtenir une valeur d'un tableau sous condition ou juste la première valeur

Étant donné JSON structuré comme ceci:

{
   "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]"
      }
   ]
}

Je voudrais un JSONPath expression pour obtenir le premier email avec le statut VERIFIED et s'il n'y en a pas, alors juste le premier email dans le tableau. Donc, étant donné l'exemple ci-dessus, le résultat serait [email protected]. Étant donné cet exemple:

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

le résultat serait [email protected].

Est-ce possible avec une expression JSONPath?

5
jhericks

Vous avez effectivement 2 expressions JSONPath, où le second (premier email) ne doit être évalué que si le premier (premier email vérifié) ne renvoie rien, donc je ne pense pas que vous puissiez les évaluer simultanément, en une seule fois. expression.

Vous pouvez les appliquer les unes après les autres, cependant:

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

Si le tableau de courrier électronique est vide, ctx.read("$.emails[0].email") renverra null au lieu de déclencher une exception, grâce à l'option optionSUPPRESS_EXCEPTIONS.


Si vous ne connaissez pas le nombre de chemins à l'avance:

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

Le optionALWAYS_RETURN_LIST signifie que le type de retour est une liste, même si vous avez un ou zéro résultats.

8
approxiblue

Ce code devrait fonctionner parfaitement pour vous 

//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