2016-12-17 53 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

相关问题