2014-03-03 32 views
0

我有一個Json數據被從服務器中拉出。這些數據包含幾個對象和數組。使GsonRequest接受空列表或空數組

第一個模型是如下:

{ 
    "results": [ 
    { 
     "id": "17", 
     "name": "Accessories", 
     "child": [ 
     { 
      "id": "371", 
      "name": "Belt" 
     }, 
     { 
      "id": "55", 
      "name": "Derp" 
     }, 
     ... 
     ] 
    } 
    ] 
} 

然而,一些results陣列的不具有child陣列。相反,它有一個空值的字符串。

{ 
    "results": [ 
    { 
     "id": "19", 
     "name": "Stuff", 
     "child": "" 
    } 
    ] 
} 

當執行的代碼,它返回該行:

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING 

這是模型的樣子:

public class CategoryModel { 
    @SerializedName("id") 
    private String category_id; 
    private String name; 
    private ArrayList<CategoryChildModel> child; 

    ... 
} 

這是我如何實現GsonRequest(其使用Volley作爲背景asynctask):

private void loadCategory() { 
    mRequestQueue = Volley.newRequestQueue(getActivity()); 

    String url = Constants.CATEGORIES_LIST; 

    GsonRequest<CategoryContainer> myReq = new GsonRequest<CategoryContainer>(
      Request.Method.GET, url, CategoryContainer.class, 
      createMyReqSuccessListener(), createMyReqErrorListener()); 

    mRequestQueue.add(myReq); 
} 

那麼,任何人都知道如何讓空對象通過GsonRequest?

+1

我想你應該最好告訴你的服務器管理員或後端工程師不要發送這樣的數據。他們要麼根本不發送孩子,要麼發送爲空。 – tasomaniac

回答

4

其實你的json響應應該返回一個空數組而不是空字符串。但是,如果你沒有一個選項來改變服務器的響應,那麼你可以嘗試編寫自定義的JSON解串器:

class ChildDeserializer implements JsonDeserializer<ChildHolder> { 
    @Override 
    public ChildHolder deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 
     String currentValueOfChild = json.toString(); 
     Log.d("ChildDeserializer", "ChildDeserializer: child=" + currentValueOfChild); 

     ChildHolder childHolder = null; 
     if (json instanceof JsonArray) { 
      Log.d("ChildDeserializer", "ChildDeserializer: We have an array for 'child'"); 

      Type listType = new TypeToken<List<Child>>() {}.getType(); 

      JsonArray jsonArray= json.getAsJsonArray(); 

      childHolder = new ChildHolder(); 
      childHolder.childList = context.deserialize(jsonArray, listType); 
     } 

     return childHolder; 
    } 
} 

您迴應Java模型應如下:

class Response { 
    List<Result> results; 
} 

class Result { 
    private String id, name; 
    private ChildHolder child; 
} 

class ChildHolder { 
    private List<Child> childList; 
} 

class Child { 
    private String id, name; 
} 

應用解串器,而解析JSON到Java模型:

String jsonTest1 = "{\"results\":[{\"id\":\"17\",\"name\":\"Accessories\",\"child\":[{\"id\":\"371\",\"name\":\"Belt\"},{\"id\":\"55\",\"name\":\"Derp\"}]}]}"; 
String jsonTest2 = "{\"results\":[{\"id\":\"19\",\"name\":\"Stuff\",\"child\":\"\"}]}"; 

GsonBuilder gsonBuilder = new GsonBuilder(); 
gsonBuilder.registerTypeAdapter(ChildHolder.class, new ChildDeserializer()); 

Gson gson = gsonBuilder.create(); 
Response response1 = gson.fromJson(jsonTest1, Response.class); 
Response response2 = gson.fromJson(jsonTest2, Response.class); 

還請read this link進一步的信息。

+0

感謝您的解決方案。但是,我不確定要在'deserialize()'方法中放置什麼。 '// TODO解析json並填充childList'請你指導我如何填充childList? – AimanB

+0

我還需要使用'createMyReqSuccessListener()'作爲成功偵聽器,還是使用Deserialization? – AimanB

+1

好吧,我已經用工作代碼編輯了我的答案。 – Devrim

1

編寫自定義序列化程序的另一種選擇是簡單地將空字符串轉換爲JSON中的空數組。那麼你的班級可以保持現狀:

class ChildDeserializer implements JsonDeserializer<CategoryModel> 
{ 
    @Override 
    public ChildHolder deserialize(JsonElement json, Type typeOfT, 
            JsonDeserializationContext context) 
             throws JsonParseException { 

     JsonObject obj = json.getAsObject(); 
     JsonElement e = obj.get("child"); 
     if (e.isJsonPrimitive()) // it's a String 
     { 
      obj.remove("child"); 
      obj.add("child", new JsonArray()); 
     } 

     return new Gson().fromJson(obj, CategoryModel.class); 
    } 
}