2017-01-04 4 views
3

Предположим, что у нас есть такой json, который не может быть изменен. И мы хотим уничтожить его с помощью Gson.Пропустить иерархию при десериализации с помощью Gson

{ 
    "user": { 
    "some_ids": { 
     "useless_key": [ 
     "22a074ff-91bf-4599-9a9e-374d3f01b6e0", 
     "66c8ce85-f162-4d92-a836-198a17764efa", 
     "d0519a9e-bfa2-446c-bb98-746136a3e513" 
     ] 
    } 
    } 
} 

Мы хотим deserialise его в классе User как этот:

public class User { 
    @SerializedName("some_ids") 
    List<String> someIds; 
} 

Вопрос: простое решение было бы создать UselessKey класс обертку и поместить someIds список в Это.

Но есть ли способ сказать Gson пропустить узел useless_key и непосредственно deserialise List внутри someIds?

ответ

-1

Просто не создавайте переменную и геттер и сеттер в классе модели. Затем он не будет разбирать ключ, который не найден.

+2

Не будет ли это просто пропустить все данные внутри ключа, и я думаю, что вопрос здесь должен также иметь эти данные? –

0

Поскольку вы все еще должны отмечать поле, которое должно обрабатываться по-разному, Gson не предоставляет ничего подобного. Однако вы можете реализовать такое поведение. Ближе всего к вашему запросу @JsonAdapter

Предположим, у вас есть

private static final String JSON = "{\n" 
     + " \"user\": {\n" 
     + " \"some_ids\": {\n" 
     + "  \"useless_key\": [\n" 
     + "  \"22a074ff-91bf-4599-9a9e-374d3f01b6e0\",\n" 
     + "  \"66c8ce85-f162-4d92-a836-198a17764efa\",\n" 
     + "  \"d0519a9e-bfa2-446c-bb98-746136a3e513\"\n" 
     + "  ]\n" 
     + " }\n" 
     + " }\n" 
     + "}"; 

public static void main(final String... args) { 
    final Gson gson = new Gson(); 
    final Response response = gson.fromJson(JSON, Response.class); 
    out.println(response.getUser().getSomeIds()); 
} 

определяется DTO Response класс, как следует:

final class Response { 

    private Response() { } 

    @SerializedName("user") 
    private final User user = null; 

    User getUser() { return user; } 

    static final class User { 

     private User() { } 

     @SerializedName("some_ids") 
     @JsonAdapter(IdsTypeAdapter.class) 
     private final List<String> someIds = null; 

     List<String> getSomeIds() { return someIds; } 

    } 

} 

тип адаптера, указанный в @JsonAdapter(IdsTypeAdapter.class) выше может быть реализован в виде следует:

final class IdsTypeAdapter 
     extends TypeAdapter<List<String>> { 

    private static final String USELESS_PROPERTY = "useless_key"; 

    private IdsTypeAdapter() { 
    } 

    @Override 
    public void write(final JsonWriter writer, final List<String> value) { 
     throw new UnsupportedOperationException(); 
    } 

    @Override 
    public List<String> read(final JsonReader reader) 
      throws IOException { 
     reader.beginObject(); 
     if (!reader.nextName().equals(USELESS_PROPERTY)) { 
      throw new UnsupportedOperationException("Expected: " + USELESS_PROPERTY); 
     } 
     reader.beginArray(); 
     final List<String> ids = new ArrayList<>(); 
     while (reader.peek() == STRING) { 
      ids.add(reader.nextString()); 
     } 
     reader.endArray(); 
     reader.endObject(); 
     return unmodifiableList(ids); 
    } 

} 

Адаптер типа выше довольно прост и способствует чтению потока, чтобы повысить производительность (адаптеры типа также требуются аннотацией @JsonAdapter). И результат:

[22a074ff-91bf-4599-9a9e-374d3f01b6e0, 66c8ce85-f162-4d92-a836-198a17764efa, d0519a9e-bfa2-446c-bb98-746136a3e513]

Другой вариант использование десериализаторов JSON (может быть зарегистрировано в GsonBuilder), но последние оказывают влияние на производительность, поскольку они требуют, чтобы все дерево JSON было создано до начала процесса десериализации. Еще одна проблема с десериализаторами JSON заключается в том, что Gson не поддерживает пользовательские аннотации, поэтому для того, чтобы отмечать «специальные» поля, вам все равно нужно создать класс-оболочку, такой как class StringIds extends ArrayList<String>, который позже даже потребовал бы контекста десериализации для десериализации заданного JsonElement до List<String>, а затем перенаправлено обратно на StringIds. Это дорого. Я бы пошел с адаптерами типа.