当前位置: 首页 > 知识库问答 >
问题:

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

孟英光
2023-03-14

我的类有一个自定义反序列化程序,如下所示:

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);

在我的反序列化方法中,json的值如下{“linkedTo”:“COUNT”}然后它作为{linkedTo=COUNT}加载到数据映射中。我想看看是否有任何方法可以让数据映射的所有值都是小写的,所以它应该像{linkedTo=COUNT}那样自动存储在数据映射中,而不是像这样{linkedTo=COUNT}

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

更新:

以下是我的JSON内容:

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

共有1个答案

许永年
2023-03-14

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

新的应用程序应该更喜欢TypeAdapter,它的流API比这个接口的树API更高效。

更多信息。

问:我们如何在反序列化之前修改json内容?

解决方案之一:在反序列化之前预处理json内容,并修改其中的一些内容。

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

代码示例:

定义类型适配器工厂类型适配器

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);

输出:

这是你的问题的类似答案。

 类似资料:
  • 我有一个JestClient(elasticsearch)响应,我试图将其反序列化为一个对象。该对象包含两个DateTime字段,而在响应中,它们是字符串,因此我得到: 所以,我创建了一个自定义反序列化器来解决这个问题…然而,无论我做什么,我总是得到同样的错误。不知何故它没有注册使用它? 最后,我试图解析JestClient响应的代码: 无论我尝试什么,我总是得到上面的错误,我甚至不确定在这一点上

  • 问题内容: 我需要反序列化json,它是日期/长值的数组。这是返回的JSON的示例: 使用GSON,我可以将其反序列化为,但希望能够将其转换为类似以下内容的方法: 我似乎找不到一种方法来指示GSON将JSON映射的键/值映射到我的自定义类中的日期/值字段。有没有办法做到这一点,还是地图列表是唯一的路线? 问题答案: 您需要编写一个自定义解串器。您还需要使用可以实际解析的时区格式。无论是也将匹配,这

  • 问题内容: 我在使用Gson解析JSON响应时遇到问题。 JSON字串: 我有这两个课程: 但是当使用Gson解析这个时我有一个异常。我知道这是因为响应数组的第一个元素不是对象,而是整数。 所以问题是,我能以某种方式解决它吗? 问题答案: 您必须编写一个 自定义反序列化器 。我会做这样的事情: 首先,您需要包括一个新的类,而不是已有的两个类: 然后,您需要一个自定义解串器,类似于以下内容: 然后,

  • 问题内容: 确定,所以我编辑了问题,因为它不够清楚。 编辑2 :更新了JSON文件。 我在Android应用程序中使用GSON,我需要解析来自服务器的JSON文件,这些文件有点太复杂了。我不想让我的对象结构太沉重,所以我想简化内容: 所以我的对象的结构将不是JSON文件的结构。 例如,如果在JSON中,我有以下内容: 我不想保留我当前的对象结构,即一个对象,其中包含一个和一个“总计”。但是我只想将

  • 据我所知,gson不会自动将java.util.Date对象序列化和反序列化为ISO字符串,比如“yyyy-mm-ddthh:mm:ssz”或“2014-04-15t18:22:00-05:00”。因此,为了让我在客户机(使用gson改型)和服务器之间正确地通信日期,我需要指定gson的日期格式。以下是我所做的: 添加。SetDateFormat行就足以让gson正确地将时间戳字符串反序列化为日期

  • I'va是一个OID接口,可以由许多具体类型实现: 现在我有一个具有两个字段的对象,一个使用抽象接口类型(OID)定义,另一个使用具体类型(MyOID)定义 我想使用jackson以不同的方式序列化/反序列化字段,无论它们是使用抽象接口类型还是具体类型定义的: 注意,被序列化,包括类型信息(多态序列化),而被序列化为文本 为此,我将OID接口注释为: 并为每个具体类型分配了类型id: 最后,对容器