有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何将自定义反序列化器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}加载到数据映射中。我想看看是否有任何方法可以使datamap的所有值都是小写的,因此它应该像这样自动存储在数据映射中而不是这个{linkedTo=COUNT}

有没有办法在Gson中自动实现这一点

更新:

以下是我的JSON内容:

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

共 (1) 个答案

  1. # 1 楼答案

    首先,建议使用GsonTypeAdapter代替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.