Gson TypeToken with dynamic ArrayList item type

前端 未结 9 1985
情深已故
情深已故 2020-11-22 08:55

I have this code:

Type typeOfObjectsList = new TypeToken>() {}.getType();
List objectsList = new Gson().fromJso         


        
相关标签:
9条回答
  • 2020-11-22 09:05

    Fully working solution:

    String json = .... //example: mPrefs.getString("list", "");
    ArrayList<YouClassName> myTypes = fromJSonList(json, YouClassName.class);
    
    
    public <YouClassName> ArrayList<YouClassName> fromJSonList(String json, Class<YouClassName> type) {
            Gson gson = new Gson();
            return gson.fromJson(json, TypeToken.getParameterized(ArrayList.class, type).getType());
        }
    
    0 讨论(0)
  • 2020-11-22 09:08

    This worked for me:

    public <T> List<T> listEntity(Class<T> clazz)
            throws WsIntegracaoException {
        try {
            // Consuming remote method
            String strJson = getService().listEntity(clazz.getName());
    
            JsonParser parser = new JsonParser();
            JsonArray array = parser.parse(strJson).getAsJsonArray();
    
            List<T> lst =  new ArrayList<T>();
            for(final JsonElement json: array){
                T entity = GSON.fromJson(json, clazz);
                lst.add(entity);
            }
    
            return lst;
    
        } catch (Exception e) {
            throw new WsIntegracaoException(
                    "WS method error [listEntity()]", e);
        }
    }
    
    0 讨论(0)
  • 2020-11-22 09:08

    With kotlin you can use a below functions to converting (from/to) any (JsonArray/JsonObject) just in one line without need to send a TypeToken :-

    Convert any class or array to JSON string

    inline fun <reified T : Any> T?.json() = this?.let { Gson().toJson(this, T::class.java) }
    

    Example to use :

     val list = listOf("1","2","3")
     val jsonArrayAsString = list.json() 
     //output : ["1","2","3"]
    
     val model= Foo(name = "example",email = "t@t.com") 
     val jsonObjectAsString = model.json()
    //output : {"name" : "example", "email" : "t@t.com"}
    

    Convert JSON string to any class or array

    inline fun <reified T : Any> String?.fromJson(): T? = this?.let {
        val type = object : TypeToken<T>() {}.type
        Gson().fromJson(this, type)
    }
    

    Example to use :

     val jsonArrayAsString = "[\"1\",\"2\",\"3\"]"
     val list = jsonArrayAsString.fromJson<List<String>>()
    
     val jsonObjectAsString = "{ "name" : "example", "email" : "t@t.com"}"
     val model : Foo? = jsonObjectAsString.fromJson() 
     //or 
     val model = jsonObjectAsString.fromJson<Foo>() 
    
    0 讨论(0)
  • 2020-11-22 09:10

    Option 1 - implement java.lang.reflect.ParameterizedType yourself and pass it to Gson.

    private static class ListParameterizedType implements ParameterizedType {
    
        private Type type;
    
        private ListParameterizedType(Type type) {
            this.type = type;
        }
    
        @Override
        public Type[] getActualTypeArguments() {
            return new Type[] {type};
        }
    
        @Override
        public Type getRawType() {
            return ArrayList.class;
        }
    
        @Override
        public Type getOwnerType() {
            return null;
        }
    
        // implement equals method too! (as per javadoc)
    }
    

    Then simply:

    Type type = new ListParameterizedType(clazz);
    List<T> list = gson.fromJson(json, type);
    

    Note that as per javadoc, equals method should also be implemented.

    Option 2 - (don't do this) reuse gson internal...

    This will work too, at least with Gson 2.2.4.

    Type type = com.google.gson.internal.$Gson$Types.newParameterizedTypeWithOwner(null, ArrayList.class, clazz);
    
    0 讨论(0)
  • 2020-11-22 09:12

    Since Gson 2.8.0, you can use TypeToken#getParameterized(Type rawType, Type... typeArguments) to create the TypeToken, then getType() should do the trick.

    For example:

    TypeToken.getParameterized(ArrayList.class, myClass).getType()
    
    0 讨论(0)
  • 2020-11-22 09:15

    You can actually do it. You just need to parse first your data into an JsonArray and then transform each object individually, and add it to a List :

    Class<T> dataType;
    
    //...
    
    JsonElement root = jsonParser.parse(json);
    List<T> data = new ArrayList<>();
    JsonArray rootArray = root.getAsJsonArray();
    for (JsonElement json : rootArray) {
        try {
            data.add(gson.fromJson(json, dataType));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    return data;
    
    0 讨论(0)
提交回复
热议问题