Deserialise a generic list in Gson

后端 未结 2 411
隐瞒了意图╮
隐瞒了意图╮ 2020-12-06 07:30

I want to write a generic function which deserialise a generic type List with Gson here is the code:

private  List GetListFromFile(String f         


        
2条回答
  •  一整个雨季
    2020-12-06 08:14

    The approach of use TypeToken won't work.

    new TypeToken>() 
    

    is not possible because of how generics (type erasure) and reflection works. The whole TypeToken hack works because Class#getGenericSuperclass() does the following

    Returns the Type representing the direct superclass of the entity (class, interface, primitive type or void) represented by this Class.

    If the superclass is a parameterized type, the Type object returned must accurately reflect the actual type parameters used in the source code.

    In other words, if it sees ArrayList, that's the ParameterizedType it will return and you won't be able to extract the compile time value that the type variable T would have had.

    Type and ParameterizedType are both interfaces. You can provide an instance of your own implementation.

    So, you have two options:

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

    private static class ListParameterizedType implements ParameterizedType {
    
        private Type type;
    
        public 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 list = gson.fromJson(json, type);
    

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

    Option 2: Parse the list manually and then for each element use Gson

    public  List listEntity(Class clazz)
            throws WsIntegracaoException {
        try {
            // Consuming remote method
            String strJson = getService().listEntity(clazz.getName());
    
            JsonParser parser = new JsonParser();
            JsonArray array = parser.parse(strJson).getAsJsonArray();
    
            List lst =  new ArrayList();
            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);
        }
    }
    

提交回复
热议问题