Tengo el siguiente archivo json:

{
    "path": [
        {
            "name": "account",
            "scopes": ["servicegroup_4", "servicegroup_5"]
        },
        {
            "name": "identity",
            "scopes": ["servicegroup_1"]
        }
    ]
}

A String microservice = "account" y una matriz String[] scopeJWT = {"servicegroup_4", "servicegroup_5"}.

Lo que me gustaría hacer es recorrer el json, encontrar el name que coincida con el valor String microservice y recorrer el conjunto scopes correspondiente. Si uno de los elementos del conjunto String[] scopeJWT es igual a al menos uno en el elemento del conjunto scopes, se imprimirá un OK en la consola; de lo contrario, un KO.

Entonces, en este caso específico, se imprimirá un OK porque la matriz scopes de account contiene al menos uno de los elementos de la matriz scopeJWT.

Aquí está mi código usando la biblioteca or.json.simple:

        String microservice = "account";

        String[] scopesJWT = {"servicegroup_4", "servicegroup_5"};

        JSONParser parser = new JSONParser();
        JSONObject json = (JSONObject) parser.parse(new FileReader("C:\\Users\\r.spampinato\\Desktop\\test.json"));
        JSONArray paths = (JSONArray) json.get("path");
        Iterator<JSONObject> itPath = paths.iterator();
        while (itPath.hasNext()) {
            JSONObject el = itPath.next();
            String name = el.get("name").toString();

            JSONArray scopes = (JSONArray) el.get("scopes");

            boolean isOK = false;
            if (name.contains(microservice)) {
                for (int i = 0; i < scopes.size(); i++) {
                    for (String element : scopesJWT) {
                        if (scopes.get(i).toString().contains(element)) {
                            System.out.println("OK");
                            isOK = true;
                        }
                        break;
                    }
                }

                if (!isOK) {
                    System.err.println("KO");
                }
            } 

Parece que funciona, pero si cambio el primer elemento del scopeJWT, se imprime un KO, aunque debería imprimirse un OK.

¿Alguna idea?

Gracias chicos.

EDITAR: ¿Qué pasa con poner y la cláusula else en caso de que el nombre no contenga ningún elemento de microservice? Quiero decir, en el primer if

0
rico_spm 7 sep. 2018 a las 17:46

4 respuestas

La mejor respuesta

Unos pequeños cambios y una mayor optimización.

    String microservice = "account";

    String[] scopesJWT = {"servicegroup_4", "servicegroup_5"};

    // Store all the keys in HashSet
    Set<T> keysSet = new HashSet<T>(Arrays.asList(scopesJWT));

     JSONParser parser = new JSONParser();
    JSONObject json = (JSONObject) parser.parse(new FileReader("C:\\Users\\r.spampinato\\Desktop\\test.json"));
    JSONArray paths = (JSONArray) json.get("path");
    Iterator<JSONObject> itPath = paths.iterator();
    while (itPath.hasNext()) {
        JSONObject el = itPath.next();
        String name = el.get("name").toString();

        JSONArray scopes = (JSONArray) el.get("scopes");

        if (name.contains(microservice)) {
            boolean ok = true;
            for (String element : scopesJWT) {
                    if (keysSet.contains(element)) {
                        continue;
                    } else {
                        ok = false; break;
                    }
                }
         ok == false? System.out.println("KO") : System.out.println("OK");
        } 

} El tiempo de ejecución de este algoritmo de coincidencia de matriz de cadenas es O (N)

1
Aarish Ramesh 7 sep. 2018 a las 15:14

Como ya se mencionó en la respuesta existente, su break debe estar dentro de la declaración if, de lo contrario, siempre detendría el ciclo for-each después de la primera iteración.

Después de eso mencionaste lo siguiente:

Lo intenté de esta manera, pero en este caso, 2 OK se imprimen en la consola.

Entonces, básicamente, desea salir de ambos bucles anidados después de que se imprima el primer OK. En ese caso, puede usar una etiqueta frente a su bucle externo y romper esa:

scopesLoop: for (int i = 0; i < scopes.size(); i++) {
  for (String element : scopesJWT) {
    if (scopes.get(i).toString().contains(element)) {
      System.out.println("OK");
      isOK = true;
      break scopesLoop;
    }
  }
}

if (!isOK) {
  System.err.println("KO");
}

EDITAR: una mejor alternativa es usar la respuesta de @AarishRamesh que solo hace un solo bucle en lugar de uno anidado, que es mejor para el rendimiento.

0
Kevin Cruijssen 7 sep. 2018 a las 15:19

Un pequeño cambio:
``

for (int i = 0; i < scopes.size(); i++) {
                    for (String element : scopesJWT) {
                        if (scopes.get(i).toString().contains(element)) {
                            System.out.println("OK");
                            isOK = true;
                        }
                        break;
                    }
                }

``

0
luckyclown 7 sep. 2018 a las 15:17

¿Está su declaración de descanso en el lugar correcto? ¿Solo quieres romper si encuentras una coincidencia?

if (name.contains(mcrsrvz)) {
            for (int i = 0; i < scopes.size(); i++) {
                for (String element : scopesJWT) {
                    if (scopes.get(i).toString().contains(element)) {
                        System.out.println("OK");
                        isOK = true;
                    }
                    break;
                }
            }

            if (!isOK) {
                System.err.println("KO");
            }
        } 

La declaración de interrupción aquí se ejecutará incondicionalmente después de la primera iteración del bucle for. Entonces, si la primera iteración del bucle coincide, establecerá isOK en verdadero y verá el resultado que espera.

Si la primera iteración no coincide, aún ejecutará la instrucción break sin verificar ningún otro miembro de la matriz scopesJWT.

Mueva la declaración de interrupción para que solo suceda cuando establezca isOK en verdadero y vea si eso mejora las cosas.

1
DaveH 7 sep. 2018 a las 15:06