如何在自定义反序列化器Gson中小写JsonElement值?

时间:2016-12-17 21:19:55

标签: java json gson

我的课程有自定义反序列化器,如下所示:

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...
    }
}

1 个答案:

答案 0 :(得分: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.