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

标签 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} 自动出现在数据 map 中?

有什么方法可以在 Gson 中自动执行此操作吗?

更新:

下面是我的 JSON 内容:

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

最佳答案

首先建议使用Gson TypeAdapter而不是JsonDeserializer 。所以我将用它来回答你的问题:

New applications should prefer TypeAdapter, whose streaming API is more efficient than this interface's tree API.

More information.

问题:反序列化前如何修改json内容?

解决方案之一:在反序列化之前对json内容进行预处理,修改其部分内容。

我们如何使用 TypeAdapter 来实现这一点:定义一个自定义的 TypeAdapter,在其 read 方法中获取 json 内容(该方法仅被调用)反序列化之前)并修改内容。

代码示例:

定义一个TypeAdapterFactory和一个TypeAdapter

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.

关于java - 如何在自定义反序列化器Gson中小写JsonElement值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41203175/

相关文章:

arrays - 在字典的数组中加载带有字典的 JSON 文件

php - 在输入 mysql 之前删除 Word 格式,以获得 JSON 输出

java - 使用 Google Gson 映射 Mongo id 字段

java - GSON反序列化忽略列表中的空对象

java - 在 Mac 上运行 Java 应用程序

java - 正则表达式。 (点)没有捕获字符串中的括号?

java - Arrays.asList(word.toCharArray()) 不返回列表?

java - 将 MySQL DATETIME 转换为 Android TextView 中的特定格式

java - mongodb java 使用 gson 反序列化 long

java - 在 JavaFX 项目中加载 fxml 文件时出错