2016-12-17 84 views
0

我有我的類的自定義解串器,如下圖所示:如何在自定義解串器Gson中使用JsonElement值?

private class HolderDeserializer implements JsonDeserializer<Holder> { 

    @Override 
    public Holder deserialize(JsonElement json, Type type, JsonDeserializationContext context) 
    throws JsonParseException { 

    Type mapType = new TypeToken<Map<String, String>>() {}.getType(); 
    // in the below data map, I want value to be stored in lowercase 
    // how can I do that? 
    Map<String, String> data = context.deserialize(json, mapType); 
    return new Holder(data); 
    } 
} 

這就是我如何註冊創建GSON對象時我解串器:

GsonBuilder gsonBuilder = new GsonBuilder(); 
gsonBuilder.registerTypeAdapter(Holder.class, new HolderDeserializer()); 
Gson gson = gsonBuilder.create(); 

最後,分析我的JSON這樣:

Type responseType = new TypeToken<Map<String, Holder>>() {}.getType(); 
Map<String, Holder> response = gson.fromJson(jsonLine, responseType); 

在我deserialize方法的json值來作爲這樣{"linkedTo":"COUNT"},然後將其作爲{linkedTo=COUNT}加載到數據映射中。我想看看data地圖的所有值是否可以用小寫字母表示,而不是這個{linkedTo=COUNT},它應該在數據地圖中自動存儲像這樣的{linkedTo=count}

有什麼辦法可以自動在Gson中做到這一點?

更新:

下面是我的JSON內容:

{ 
    "abc": { 
     "linkedTo": "COUNT", 
     // possibly more data... 
    }, 
    "plmtq": { 
     "linkedTo": "TITLE", 
     "decode": "TRUE", 
     // possibly more data... 
    } 
} 
+0

請分享您的JSON內容 – Devrim

+0

@DevrimTuncer更新了我的JSON的問題。 – john

回答

2

首先,它建議使用GSON TypeAdapter代替JsonDeserializer。所以我打算用它來回答你的問題:

新的應用程序應該更喜歡TypeAdapter,其流API是 比這個接口的API樹更有效。

More information.

問:我們如何修改反序列化前的JSON的內容?

解決方案之一:在反序列化之前預處理json內容並修改其中的一些內容。

我們如何才能實現這一目標與TypeAdapter:定義自定義TypeAdapter,獲得在其read方法json的內容(這是剛剛在反序列化之前調用)和修改的內容。

代碼示例:

定義TypeAdapterFactoryTypeAdapter;

TypeAdapterFactory myCustomTypeAdapterFactory = new TypeAdapterFactory() { 
      @Override 
      public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) { 

       final TypeAdapter<JsonElement> elementAdapter = gson.getAdapter(JsonElement.class); 
       final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type); // 

       return new TypeAdapter<T>() { 

        public void write(JsonWriter out, T value) throws IOException { 
         JsonElement tree = delegate.toJsonTree(value); 
         beforeWrite(value, tree); 
         elementAdapter.write(out, tree); 
        } 

        public T read(JsonReader in) throws IOException { 
         JsonElement tree = elementAdapter.read(in); 
         afterRead(tree); 
         return delegate.fromJsonTree(tree); 
        } 

        /** 
        * Modify {@code toSerialize} before it is written to 
        * the outgoing JSON stream. 
        */ 
        protected void beforeWrite(T source, JsonElement toSerialize) { 

        } 

        /** 
        * Modify {@code deserialized} before it is parsed 
        */ 
        protected void afterRead(JsonElement deserialized) { 
         if(deserialized instanceof JsonObject) { 
          JsonObject jsonObject = ((JsonObject)deserialized); 
          Set<Map.Entry<String, JsonElement>> entrySet = jsonObject.entrySet(); 
          for(Map.Entry<String,JsonElement> entry : entrySet){ 
           if(entry.getValue() instanceof JsonPrimitive) { 
            if(entry.getKey().equalsIgnoreCase("linkedTo")) { 
             String val = jsonObject.get(entry.getKey()).toString(); 
             jsonObject.addProperty(entry.getKey(), val.toLowerCase()); 
            } 
           } else { 
            afterRead(entry.getValue()); 
           } 
          } 
         } 
        } 
       }; 
      } 
     }; 

在反序列化之前我們已經添加了一個額外的過程。我們從json內容獲取entrySet,並更新了linkedTo密鑰的值。

工作樣本:

String jsonContent = "{\"abc\":{\"linkedTo\":\"COUNT\"},\"plmtq\":{\"linkedTo\":\"TITLE\",\"decode\":\"TRUE\"}}"; 

GsonBuilder gsonBuilder = new GsonBuilder(); 
gsonBuilder.registerTypeAdapterFactory(myCustomTypeAdapterFactory); 
Gson gson = gsonBuilder.create(); 

Map mapDeserialized = gson.fromJson(jsonContent, Map.class); 

輸出:

enter image description here

This is the similar answer for your question.

+0

感謝您的解決方案。問題是,我沒有pojo,也沒有pojo。這個json每20分鐘從一個數據庫傳出。如果我在數據庫中對json進行任何更改,我不希望我的應用程序與pojo緊密相關,這就是爲什麼我要在地圖中加載所有內容的原因。我們可以加載地圖中的所有內容,而不是序列化太POJO嗎? – john

+0

這只是我的json的一個示例。一般來說,我的json不僅僅是那些領域的大個子。 – john

+0

@david是的,我已經更新了我的答案。 – Devrim

相關問題