Search code examples
javaarraysreflectionillegalargumentexceptionsetvalue

Setting value of array using java reflection


I have created generic json parser using java reflection, but there is a error that i am not able to solve.

Method (at the bottom of this question), receives subclass of my custom Model class. I iterate through fields and set values from json. If subclass contains array property of some other class (which is again, subclass of Model), i've created small recursion to fill those objects.

Eg.

class UserModel extends Model
{
    @JsonResponseParam(Name="userName")
    public String Name;

    @JsonResponseParam(Name="friends")
    public FriendModel[] Friends;
}

At the end UserModel should be filled with Friends. (JsonResponseParam is custom anotation, and Name value is used as property for getting values from json)

Result of this method is IllegalArgumentException, and it is thrown on

field.set(t, values.toArray());

Here is the method:

protected <T extends Model> T getModel(T t)
{
    Field[] fields = t.getClass().getFields();

    for (Field field : fields) {
        Annotation an = field.getAnnotation(JsonResponseParam.class);

        if(an != null){
            try 
            {               
                if(field.getType() == boolean.class)                
                    field.setBoolean(t, t.getBool(((JsonResponseParam)an).Name()));

                if(field.getType() == String.class)
                    field.set(t,  t.getString(((JsonResponseParam)an).Name()));

                if(field.getType() == int.class)
                    field.setInt(t,  t.getInt(((JsonResponseParam)an).Name()));

                if(field.getType() == Date.class)
                    field.set(t,  t.getDate(((JsonResponseParam)an).Name()));

                if(field.getType().isArray()){

                    ArrayList<Model> modelArray = t.getModelArray(((JsonResponseParam)an).Name());
                    ArrayList<Model> values = new ArrayList<Model>();

                    for (Model model : modelArray) {

                        Class<? extends Model> arrayType = field.getType().getComponentType().asSubclass(Model.class);
                        Model m = arrayType.newInstance();
                        m.jsonObject = model.jsonObject;
                        model.getModel(m);
                        values.add(m);                      
                    }

                    field.set(t, values.toArray());
                }

            } catch (IllegalArgumentException e) { 
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            }
        }
    }

    return t;
}

I am suspecting on class type inconsistency between field and values..

Thank you for your time.


Solution

  • toArray() only return an Object[] so it cannot be assigned to any other array type.

    What you want is

    field.set(t, values.toArray(Array.newInstance(field.getType().getComponentType(), values.size()));
    

    This will create an array of the type to match the field.

    See Array.newInstance