2014-10-19 2 views
0

Я хочу десериализовать ответ JSON, но я не уверен в этом формате. Формат может варьироваться в каждом случае. Например, ответ содержит поле с именем «ошибка», которое может быть ложным (логическим) или объектом, который описывает ошибку, например. "error": {"code": xxx, "description": "etc"}Gson deserializer поддерживает несколько типов

Как следует реализовать класс, который охватывает оба случая? Есть какой-либо способ сделать это?

Благодаря

+0

Deserialize в карты и списки, а затем проверяйте данные по мере доступа к нему. –

ответ

0

Я предпочел бы, используя TypeAdapter для Вашего случая:

private static class Error { 
    private boolean hasError; 
    private int code; 
    private String description; 
} 

private static class ErrorTypeAdapter extends TypeAdapter<Error> { 

    @Override 
    public Error read(JsonReader jsonReader) throws IOException { 
     Error response = null; 

     jsonReader.beginObject(); 

     while (jsonReader.hasNext()) { 
      String currentJsonName = jsonReader.nextName(); 
      if("error".equals(currentJsonName)) { 
       response = new Error(); 
       try { 
        response.hasError = jsonReader.nextBoolean(); 
       } catch (Exception e) { 
        response.hasError = true; 
        jsonReader.beginObject(); 
       } 
      } else if("code".equals(currentJsonName)) { 
       response.code = jsonReader.nextInt(); 
      } else if ("description".equals(currentJsonName)) { 
       response.description = jsonReader.nextString(); 
      } 
     } 
     if(response.hasError) { 
      jsonReader.endObject(); 
     } 
     jsonReader.endObject(); 

     return response; 
    } 

    @Override 
    public void write(JsonWriter jsonWriter, Error response) 
      throws IOException { 
     jsonWriter.beginObject(); 
     jsonWriter.name("hasError").value(response.hasError); 
     jsonWriter.name("code").value(response.code); 
     jsonWriter.name("description").value(response.description); 
     jsonWriter.endObject(); 
    } 

} 

Чтобы проверить это можно использовать:

String val1 = "{\"error\": {\"code\": 1 , \"description\":\"etc\"}}"; 
String val2 = "{\"error\": false}"; 

final GsonBuilder gsonBuilder = new GsonBuilder(); 
gsonBuilder.registerTypeAdapter(Error.class, new ErrorTypeAdapter()); 
gsonBuilder.setPrettyPrinting(); 

final Gson gson = gsonBuilder.create(); 

gson.fromJson(val1, Error.class); 
gson.fromJson(val2, Error.class); 

Вы можете прочитать больше о TypeAdapters here, а также некоторые отличные примеры here.

+0

Почему 'jsonReader.endObject();' называется 2 раза? – ApollonDigital

+0

@ApollonDigital, если вы отлаживаете тестовые примеры (val1 и val2), вы поймете это. Если значение ошибки json переустанавливает логическое значение, это будет примитивный тип. Но если значение ошибки json возвращает код и значение строки desc, это будет внутренний объект, которому требуется еще один объект beginObject и endObject. – Devrim

+0

Ницца! ... но у меня также есть другое поле с именем «response»: {...} (после поля «error»), когда «ошибка» ошибочна с ответом? Могу ли я каким-то образом вызвать считыватель по умолчанию для части ответа? – ApollonDigital

Смежные вопросы