Converter um array json em um ArrayList<T>

8 respostas
R

Bom dia a todos,
estou com um problema ao ler um json e tentar convertê-lo em um tipo generico.
se vocês olharem o codigo abaixo eu tenho dois metodos que fazem a mesma coisa porem so trocam a classe
eu gostaria de construir apenas um metodo estatico e ele seria o responsavel pela conversão de qualquer json para qualquer classe do meu sistema
como eu implementaria generics nessa classe ?

private List converterJsonToListDescontoUfCondicao(String json) {
        Gson gson = getGson();
        Type listType = new TypeToken<Map<String,List<DescontoUfCondicao>>>() {}.getType();
        Map<String,List<DescontoUfCondicao>> mapa = gson.fromJson(json, listType);
        List<DescontoUfCondicao> lista = null;
        for( String key : mapa.keySet()){
           lista = mapa.get(key);     
        }
        
        return lista;
    }

    private List converterJsonToListDescontoProdutoCondicao(String json) {
        Gson gson = getGson();
        Type listType = new TypeToken<Map<String,List<DescontoProdutoCondicao>>>() {}.getType();
        Map<String,List<DescontoProdutoCondicao>> mapa = gson.fromJson(json, listType);
        List<DescontoProdutoCondicao> lista = null;
        for( String key : mapa.keySet()){
           lista = mapa.get(key);     
        }
        
        return lista;
    }

8 Respostas

S

Rodrigo estou com um script parecido com o seu…

pra essa linha aqui, qual import vc está usando?

Type listType = new TypeToken<Map<String,List<DescontoUfCondicao>>>() {}.getType();

abs

C

Tenta passar além da string json uma instancia de Class ai tu faz assim

// Pega uma referencia a class private List converterJsonToListDescontoProdutoCondicao(String json, Class<T> classe) { Gson gson = getGson(); // Obtem uma instancia de TypeToken a partir dela e gera o Type como antes Type listType = TypeToken.get(classe).getType(); // Como no retorno não foi determinado um tipo e é possivel fazer um cast com segurança // e internamente no metodo não é utilizado nada do list eu fiz assim com Object Map<String, Object> mapa = gson.fromJson(json, listType); List<Object> lista = null; for( String key : mapa.keySet()){ lista = mapa.get(key); } return lista; }

Eu não testei o codigo e nunca utilizei esta API para json mas de acordo com a documentação acho que dá certo, testa ai e dá o feedback, o retorno poderia ser mais especifico caso fosse utilizado em uma classe a parte com a utilização de generics e os metodos poderiam ser sobrecarregados pra abranger um escopo maior, mas acho que assim funciona, só vai dar problema caso o a string não resulte em um List, acho que com reflection dá pra resolver isso.

R

salmaox:
Rodrigo estou com um script parecido com o seu…

pra essa linha aqui, qual import vc está usando?

Type listType = new TypeToken<Map<String,List<DescontoUfCondicao>>>() {}.getType();

abs

Salmaox

segue abaixo lista de imports de uma classe minha de testes:

import com.google.gson.*;
import com.google.gson.reflect.TypeToken;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import java.io.*;
import java.lang.reflect.Type;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Map;
import org.codehaus.jettison.json.JSONException;
R

CharlesAlves:
Tenta passar além da string json uma instancia de Class ai tu faz assim

// Pega uma referencia a class private List converterJsonToListDescontoProdutoCondicao(String json, Class<T> classe) { Gson gson = getGson(); // Obtem uma instancia de TypeToken a partir dela e gera o Type como antes Type listType = TypeToken.get(classe).getType(); // Como no retorno não foi determinado um tipo e é possivel fazer um cast com segurança // e internamente no metodo não é utilizado nada do list eu fiz assim com Object Map<String, Object> mapa = gson.fromJson(json, listType); List<Object> lista = null; for( String key : mapa.keySet()){ lista = mapa.get(key); } return lista; }

Eu não testei o codigo e nunca utilizei esta API para json mas de acordo com a documentação acho que dá certo, testa ai e dá o feedback, o retorno poderia ser mais especifico caso fosse utilizado em uma classe a parte com a utilização de generics e os metodos poderiam ser sobrecarregados pra abranger um escopo maior, mas acho que assim funciona, só vai dar problema caso o a string não resulte em um List, acho que com reflection dá pra resolver isso.

CharlesAlves,
Se eu tento converter para Object não gera nenhum erro,
agora seu eu tentar converter para ele me retorna um LinkedHashMap e da erro, estou postando minha classe abaixo.

package app;


import com.google.gson.*;
import com.google.gson.reflect.TypeToken;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import java.io.*;
import java.lang.reflect.Type;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.codehaus.jettison.json.JSONException;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author rodrigo
 */
public class Main {
    
    public static void main(String args[]) throws FileNotFoundException, IOException, URISyntaxException, JSONException{
        
        String json = readJsonFromFile();
        Gson gson = getGson();
        
        Type type = null;
        List<DescontoQuantidadeCondicao> lista = null ;

         // Primeiro conversao para object --> OK        
         // verifica se é um array 
 
        if( json.contains("[")){
            type = new TypeToken<Map<String,List<DescontoQuantidadeCondicao>>>(){}.getType();
            lista = (List<DescontoQuantidadeCondicao>) converterJsonToObject(json, type);
        }else{
            type = new TypeToken<Map<String,DescontoQuantidadeCondicao>>(){}.getType();
            lista = new ArrayList<DescontoQuantidadeCondicao>();
            lista.add((DescontoQuantidadeCondicao) converterJsonToObject(json, type));        
        }
        
        
        System.out.println(lista.get(0).getId());
        // saida esta ok ... 
        
        // agora tenta converter usando Generics        

        List<DescontoQuantidadeCondicao> lista2 = converterJsonToList(json, DescontoQuantidadeCondicao.class);
        
        
        System.out.println(lista2.get(0).getId());
        // da a seguinte mensagem de erro.
        //        Exception in thread "main" java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to app.DescontoQuantidadeCondicao
	// at app.Main.main(Main.java:59)        


        
    }
    
   private static Object converterJsonToObject( String json, Type type){
        Gson gson = getGson();
        Map<String, Object> mapa = gson.fromJson(json, type);
        Object obj = null;
        for( String key : mapa.keySet()){
           obj = mapa.get(key);     
        }
        return obj;
   } 
   
   private static <T> List<T> converterJsonToList(String json, Class<T> aClass) {
        
        Type type = null;
        List<T> lista = null ;
        
        if( json.contains("[")){
            type = new TypeToken<Map<String,List<T>>>(){}.getType();
            lista= (List<T>) converterJsonToObject(json, type);
        }else{
            type = new TypeToken<Map<String,T>>(){}.getType();
            lista = new ArrayList<T>();
            lista.add((T) converterJsonToObject(json, type));
        }
        return lista;
    }
    
    public static Gson getGson(){
        GsonBuilder builder = new GsonBuilder(); 
        String formato = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").toPattern();
        builder.setDateFormat(formato);
        return builder.create();
    }
    
    public static String readJsonFromFile() throws FileNotFoundException, URISyntaxException, IOException{
        File file = new File(Produto.class.getResource("desconto.js").toURI());
        BufferedReader br = new BufferedReader(new FileReader(file));
	String linha = "";
        String json  = "";
        
        while( (linha = br.readLine()) != null ){	  
          json += linha;
	}
	
        br.close();
        return json;
    }
    
    public static String readWebService(){
        
        ClientConfig cc = new DefaultClientConfig();
        Client cliente = Client.create(cc);
        WebResource wr = cliente.resource("http://localhost:8080/webservice").path("descontosquantidade");
        String resposta = wr.get(String.class);
        
        return resposta;
    }
}
C

Bom definitivamente desisto de tentar xD, to desde cedo tentando e não tem jeito a forma correta de fazer para pegar o list é assim mesmo

private List converterJsonToListDescontoProdutoCondicao(String json) { Type listType = new TypeToken<List<Teste>>(){}.getType(); List<Teste> lista = new Gson().fromJson(json, listType); return lista; }
Todas as vezes que tentei fazer utilizando generics ele não reconheceu o tipo e terminou fazendo uma instancia de Object, com isto ele terminava criando uma instancia de LinkedHashMap, por isto está dando lançando esta exception. Mas vou pesquisar mais, ainda não sei exatamente o porque de não estar dando certo e isto me incomoda.

S

Charles usei dessa forma também, deu certo…

Type collectionType = new TypeToken<List<Teste>>(){}.getType();
List<Teste> lista = g.fromJson(str, collectionType);

return lista;
R

O problema é ao usar generics salmaox…

I

Pois é estou com o mesmo erro, e o legal de usar o tipo generic é que se não for assim eu terei que criar uma classe para cada tipo que eu for deserializar.

:?

Criado 6 de março de 2012
Ultima resposta 9 de nov. de 2012
Respostas 8
Participantes 4