Pegando dados de um JSON

7 respostas
C

Ola a todos!

Eu li mil topicos e blogs sobre manipulação de JSON em Java, mas todos só explicavam como criar (PUT etc) um JSON e não pegar (GET) dados de um JSON.

Por exemplo (veja o comentario)

{"bindings": [
        {"ircEvent":[
              {"ircEvent": "ERROR1"},
              {"bindings": "OK1"}
         ]},
        {"ircEvent":[
              {"ircEvent": "ERROR2"}, 
              {"bindings": "OK2"}  // <-------QUERO PEGAR ESSE ELEMENTO
         ]},
        {"ircEvent":[
              {"ircEvent": "ERROR3"}, //<-------QUERO PEGAR ESSE ELEMENTO TAMBEM
              {"bindings": "OK3"}
         ]}
    ]
}

se eu utilizar o metodo:

getString("bindings")

provavelmente não vai dar certo , porque existe varios “bindings”.
Como faço?

Obrigado, desde já!

7 Respostas

D

Existem vários parsers para JSON implementados em Java.
Um deles é o Jettison. O .jar da última versão pode ser obtida aqui: http://repository.codehaus.org/org/codehaus/jettison/jettison/1.2/jettison-1.2.jar

Enfim, segue o exemplo:

String jsonData = "{\"bindings\": [" +
        "{\"ircEvent\":["
        + "{\"ircEvent\": \"ERROR1\"},"
        + "{\"bindings\": \"OK1\"}"
        + "]},"
        + "{\"ircEvent\":["
        + "{\"ircEvent\": \"ERROR2\"},"
        + "{\"bindings\": \"OK2\"} "
        + "]},"
        + "{\"ircEvent\":["
        + "{\"ircEvent\": \"ERROR3\"},"
        + "{\"bindings\": \"OK3\"}"
        + "]}"
        + "]"
        + "}";

try {

    // cria um objeto a partir dos dados em JSON
    JSONObject jObj = new JSONObject( jsonData );

    // legal, tem um objeto, e agora pega a propriedade bindings
    // que é um array
    JSONArray jArray = jObj.getJSONArray( "bindings" );

    // itera pelo array
    for ( int i = 0; i < jArray.length(); i++ ) {

        // para cada posição do array, pega o objeto
        JSONObject jo = jArray.getJSONObject( i );

        // é, mas cada objeto tem um atributo chamado ircEvent
        // que é um array
        JSONArray jArrayIrcEvent = jo.optJSONArray( "ircEvent" );

        // itera pelo array obtido na posição atual
        for ( int j = 0; j < jArrayIrcEvent.length(); j++ ) {

            // pega o objeto de novo...
            JSONObject joi = jArrayIrcEvent.getJSONObject( j );

            // para cada objeto obtido, verifica se o atributo
            // existe. se existe, mostra os dado associado
            if ( joi.has( "ircEvent" ) ) {
                System.out.println( joi.getString( "ircEvent" ) );
            } else if ( joi.has( "bindings" ) ) {
                System.out.println( joi.getString( "bindings" ) );
            }

        }

    }

} catch ( JSONException exc ) {
    exc.printStackTrace();
}

Agora, só uma coisa. Vc que estruturou esse JSON? Se sim, sugiro que repense a estrutura... Vc usa o nome dos atributos de forma repetida em cada nível da hierarquia. Caso o formato não seja seu, desconsidere o que falei.

Não esqueça de colocar o .jar do Jettison no classpath da sua aplicação.

[]´s

C

Muito interessante :smiley:
Então, nem fui eu quem estruturei, ele vem desse jeito praticamente.

LINHA 24: Então quando vc pega o array “bindings”, o programa pega o PRIMEIRO array com nome “bindings”, no caso se existir mais que um array com esse nome?

Obrigado pela ajuda, davidbuzatto!

D

cawecoy:
Muito interessante :smiley:
Então, nem fui eu quem estruturei, ele vem desse jeito praticamente.

LINHA 24: Então quando vc pega o array “bindings”, o programa pega o PRIMEIRO array com nome “bindings”, no caso se existir mais que um array com esse nome?

Obrigado pela ajuda, davidbuzatto!

Isso vai “ferir” a estrutura. Vc tem duas propriedades com o mesmo nome em um objeto? Não.
Não testei, mas provavelmente deve dar algum erro no parse. Caso não haja, vai depender de como o parser trata isso. Se ele pega a primeira que achar ou a última.
Enfim, como eu disse, conceitualmente vc não pode ter dos atributos com o mesmo nome em um objeto, mas sinceramente não sei como isso é tratado no JSON.
Vou testar, espera ai :smiley:

D

Acabei de testar. Funciona, mas o jettison pega a última ocorrência, sempre baseado no identificador.
Uma situação mais incomum ainda seria ter identificadores iguais (situação q vc perguntou) e a cada identificador estar atribuido um valor de tipo diferente.
Por exemplo: primeiro o "bindings" que é um array e segundo o "bindings" que é uma String. Se vc tentar pegar um array, vai dar erro. Pq ele vai tentar pegar o último bindings (que é uma String).

No código que passei, isso aqui funciona:
// dois arrays bindings (primeiro com dados, segundo vazio)
{"bindings": [
        {"ircEvent":[
              {"ircEvent": "ERROR1"},
              {"bindings": "OK1"}
         ]},
        {"ircEvent":[
              {"ircEvent": "ERROR2"}, 
              {"bindings": "OK2"}
         ]},
        {"ircEvent":[
              {"ircEvent": "ERROR3"},
              {"bindings": "OK3"}
         ]}
    ],
  "bindings": []
}

// dois arrays bindings (primeiro vazio, segundo com dados)
{  "bindings": [],
    "bindings": [
        {"ircEvent":[
              {"ircEvent": "ERROR1"},
              {"bindings": "OK1"}
         ]},
        {"ircEvent":[
              {"ircEvent": "ERROR2"}, 
              {"bindings": "OK2"}
         ]},
        {"ircEvent":[
              {"ircEvent": "ERROR3"},
              {"bindings": "OK3"}
         ]}
    ]
}

// uma string binding e um array binding 
// funciona, pq pega a última ocorrência (que é um array) e não a primeira.
{  "bindings": "bla bla bla",
    "bindings": [
        {"ircEvent":[
              {"ircEvent": "ERROR1"},
              {"bindings": "OK1"}
         ]},
        {"ircEvent":[
              {"ircEvent": "ERROR2"}, 
              {"bindings": "OK2"}
         ]},
        {"ircEvent":[
              {"ircEvent": "ERROR3"},
              {"bindings": "OK3"}
         ]}
    ]
}
Entretanto, isso aqui dá erro:
// um array binding e uma string binding
// não funciona, pq pega a última ocorrência (que é string) e não a primeira.
{"bindings": [
        {"ircEvent":[
              {"ircEvent": "ERROR1"},
              {"bindings": "OK1"}
         ]},
        {"ircEvent":[
              {"ircEvent": "ERROR2"}, 
              {"bindings": "OK2"}
         ]},
        {"ircEvent":[
              {"ircEvent": "ERROR3"},
              {"bindings": "OK3"}
         ]}
    ],
    "bindings": "bla bla bla",
}

Mas como eu falei, tem um erro conceitual, pq vc não deveria ter dois atributos com o mesmo nome.
[]´s

C

hm…
Mas o que eu quiz dizer era… se ele pega sempre o elemento do menor nível, no caso o PRIMEIRO nível. (e realmente pega)
Acho q um erro conceitual é 2 elementos com mesmo nome em um mesmo nível.

Eu estou fazendo crawling de um DOM com o http://developer.yahoo.com/yql/, e a requisição HTTP me retorna um json cheio de div’s span’s li’s a’s, um dentro do outro, e isso q me confundiu bastante!

bom, muito obrigado pela ajuda :wink:
COY.

D

cawecoy:
hm…
Mas o que eu quiz dizer era… se ele pega sempre o elemento do menor nível, no caso o PRIMEIRO nível. (e realmente pega)
Acho q um erro conceitual é 2 elementos com mesmo nome em um mesmo nível.

Mas é exatamente isso que eu disse. Olhe os exemplos. O nível mais alto do objeto (primeiro bloco de chaves) tem dois bindings. Eu inseri um para ver se dava erro ou se funcionava.
Quanto ao que é obtido, ele sempre vai pegar o atributo do objeto corrente, ou seja, o que foi feito o parse inicial. Sempre vai de fora para dentro.

[]´s

C

tem razao! ^^

Criado 25 de julho de 2010
Ultima resposta 26 de jul. de 2010
Respostas 7
Participantes 2