dimanche 6 janvier 2019

Get the type of a nested list using reflections Ex: List

i'm working on a JsonObject converter using reflections, but im having a problem is when i reach some field like List<List<Object>>

Im using annotations to locate the fields that i want to write in the JsonObject, then i use recursive methods to save and retrieve the data, i know how to get the Type from a field like List<Object> but i need to get each Type contained on the list when i retrieve all the data in the line ParameterizedType parameterizedType = (ParameterizedType) field.getGenericType();

in the getValue method:

private Object getValue(JsonElement jsonElement, Field field, Class<?> type)

  • jsonElement is the value from the json that will be set to a field or as part of a list
  • field is the Field where the final return of the method will be placed
  • type is the expected class of return, a thread of recursion ends when a primitive is returned

The method from below is used to return value to set at the field on the parameter. This is working fine for single List<Object> field, but i need a way to get the Generic Type of the List contained in the outer List and so on for all the nested lists.

private Object getValue(JsonElement jsonElement, Field field, Class<?> type) throws Exception {
    Class<?> fieldClass = field.getType();
    JsonField jsonField = field.getAnnotation(JsonField.class);
    if(jsonElement instanceof JsonPrimitive) {
        JsonPrimitive jsonPrimitive = (JsonPrimitive) jsonElement;
        if(jsonPrimitive.isBoolean()) {
            return jsonPrimitive.getAsBoolean();    
        }
        else if(jsonPrimitive.isNumber()) {
            if(type.equals(byte.class)) {
                return jsonPrimitive.getAsByte();
            }
            else if(type.equals(short.class)) {
                return jsonPrimitive.getAsShort();
            }
            else if(type.equals(int.class)) {
                return jsonPrimitive.getAsInt();
            }
            else if(type.equals(long.class)) {
                return jsonPrimitive.getAsLong();
            }
            else if(type.equals(float.class)) {
                return jsonPrimitive.getAsFloat();
            }
            else if(type.equals(double.class)) {
                return jsonPrimitive.getAsDouble();
            }
            else if(type.equals(Date.class)) {
                return new Date(jsonPrimitive.getAsLong());
            }
        }
        else if(jsonPrimitive.isString()) {
            if(type.isEnum()) {
                return Enum.valueOf(type.asSubclass(Enum.class), jsonPrimitive.getAsString());
            }
            else if(type.equals(UUID.class)) {
                return UUID.fromString(jsonPrimitive.getAsString());
            }
            else {
                return jsonField.stringType().load(jsonPrimitive.getAsString());
            }
        }
    }
    else if(jsonElement instanceof JsonObject) {
        JsonObject jsonObject = (JsonObject) jsonElement;
        Class<? extends JsonPersistent> persistent = field.getType().asSubclass(JsonPersistent.class);
        return fromJson(persistent, jsonObject);
    }
    else if(jsonElement instanceof JsonArray) {
        JsonArray jsonArray = (JsonArray) jsonElement;
        //Here is were is my problem, the recursion will not work because field does not change over the recursion cycles
        ParameterizedType parameterizedType = (ParameterizedType) field.getGenericType();
        Class<?> listClass = (Class<?>) parameterizedType.getActualTypeArguments()[0];
        List<Object> list = new LinkedList<>();
        for (JsonElement otherJsonElement : jsonArray) {
            list.add(getValue(otherJsonElement, field, listClass));
        }
        return list;
    }
    throw new Exception("No method found to deserialize " + fieldClass.getSimpleName() + " into a field");
}





Aucun commentaire:

Enregistrer un commentaire