0

Class:

public class MyList {

    public int type;
    public String text;
    public boolean[] arr;

    public MyList(int type, String text) {
        this.type = type;
        this.text = text;
        switch (type) {
        case 0:
            arr = new boolean[5];
            break;
        case 1:
            arr = new boolean[10];
            break;
        }
    }
}

JSON Data:

{ "list": [ { "type": 0, "text": "Text 1" }, { "type": 1, "question": "Text 2" } ] }

Parser:

ArrayList<MyList> getList(){
    Gson gson = new Gson();
    MyListsArray mLists = gson.fromJson(bufferString, MyListsArray.class);
    return mLists.list;
}

Class to hold the list items:

public class MyListsArray {
    public ArrayList<MyList> list;
}

Everything goes fine, I get proper values for type and text which are present in the JSON String. But the arr remains null.

Archie.bpgc
  • 23,812
  • 38
  • 150
  • 226
  • The JSON sample does not contain any boolean arrays, therefore the empty result – Pphoenix Apr 15 '14 at 11:37
  • But isn't it supposed to go through the constructor and initiate the boolean array? – Archie.bpgc Apr 15 '14 at 11:37
  • You cannot safely create a `boolean` primitive array reflexively. You need a wrapper. See: [Using GSON to parse a JSON array](http://stackoverflow.com/questions/18421674/using-gson-to-parse-a-json-array) – Mr. Polywhirl Apr 15 '14 at 11:37
  • Which int values do you get for type in the objects that are created? – Pphoenix Apr 15 '14 at 11:38
  • @Pphoenix my sample json string has both 0,1 type – Archie.bpgc Apr 15 '14 at 11:39
  • Your json does not contain the array of boolean (arr property), If you want to populate it then you need to write custom JsonDeserializer – Asif Bhutto Apr 15 '14 at 11:42
  • 1
    @bhutto Yeah. But I thought this process will go through the Constructor and eventually create a boolean array. So, how to initiate data which is not present in the Json string? – Archie.bpgc Apr 15 '14 at 11:43
  • 2
    @Archie.bpgc Gson uses the properties not getter/setter and Gson instantiate the class object by invoking the default constructor – Asif Bhutto Apr 15 '14 at 11:46
  • @bhutto One of my friend said: `If I declare the variable **type** as private, the Gson with try to find if there is a setter method for it and use it. So, in that setter method I can initialize other variables like the arr in my case.` Is that true? Because when I tried it didn't work. – Archie.bpgc Apr 16 '14 at 09:45
  • 1
    @Archie.bpgc GSON use ONLY fields(private,public,protected). Doc says : There are good arguments to support properties as well. We intend to enhance Gson in a latter version to support properties as an alternate mapping for indicating Json fields. For now, Gson is fields-based see doc here https://sites.google.com/site/gson/gson-design-document – Asif Bhutto Apr 16 '14 at 10:50

2 Answers2

2

GSon never calls a constructor of a MyList class in your code. That's why arr gets the default value. Which is null.

Denis Kulagin
  • 8,472
  • 17
  • 60
  • 129
1

You can initiate data which is not present in the Json string as below write CustomDeserializer

class CustomDeserializer implements JsonDeserializer<List<MyList>> {

    @Override
    public List<MyList> deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context) throws JsonParseException {

       JsonArray jsonArray =    jsonElement.getAsJsonObject().getAsJsonArray("list");

       List<MyList>  list=new ArrayList<>(30);
       Gson gson = new Gson();

       for (JsonElement element : jsonArray) {

                MyList ob =  gson.fromJson(element,  MyList.class);
                switch (Integer.valueOf(ob.type)) {
                case 0:
                    ob.arr = new boolean[5];
                    break;
                case 1:
                    ob.arr = new boolean[10];
                    break;
                }

               list.add(ob);
        }

        return list;
    }

Finally parse it

 Type typeOf = new TypeToken   <List<MyList>>(){}.getType();
 Gson gson = new GsonBuilder().registerTypeAdapter(typeOf, new CustomDeserializer()).create();
 List<MyList> list = gson.fromJson(builder.toString(),typeOf);

Gson documentation says, if your class doesn't have an no-args constructor and you have not registered any InstanceCreater objects, then it will create an ObjectConstructor (which constructs your Object) with an UnsafeAllocator which uses Reflection to get the allocateInstance method of the class sun.misc.Unsafe to create your class' instance.

If you do have a no-args constructor, Gson will use an ObjectConstructor which uses that default Constructor by calling

yourClassType.getDeclaredConstructor(); // ie. empty, no-args
Benoit Duffez
  • 11,839
  • 12
  • 77
  • 125
Asif Bhutto
  • 3,916
  • 1
  • 24
  • 21