2017-01-04 94 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並直接反序列化someIds裏面的列表?

回答

-1

只是不要在Model類中創建變量和getter和setter。它不會然後解析未找到的密鑰。

+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。這太貴了。我會選擇類型適配器。

相關問題