Java 使用Gson,如何序列化映射中的null而不是其他类中的null?

Java 使用Gson,如何序列化映射中的null而不是其他类中的null?,java,json,gson,Java,Json,Gson,使用Gson,我希望能够序列化Maps中的空值,但不能序列化其他类中的空值。也就是说,如果我有这样一门课: 公共类Foo{ @序列化名称(“bar”) 酒吧; @序列化名称(“我的地图”) 地图我的地图; } 如果栏字段为空,并且myMap包含一个条目“key”->null,我希望生成的JSON字符串为: { "my_map": { "key": null, } } 然而,我需要以一种非常通用的方式来工作:我有许多具有复杂层次结构的类,并且类和容器可能嵌套得很深 我尝试了以下

使用Gson,我希望能够序列化
Map
s中的空值,但不能序列化其他类中的空值。也就是说,如果我有这样一门课:

公共类Foo{
@序列化名称(“bar”)
酒吧;
@序列化名称(“我的地图”)
地图我的地图;
}
如果
字段为空,并且
myMap
包含一个条目
“key”->null
,我希望生成的JSON字符串为:

{
  "my_map": {
    "key": null,
  }
}
然而,我需要以一种非常通用的方式来工作:我有许多具有复杂层次结构的类,并且类和容器可能嵌套得很深

我尝试了以下方法:

  • 使用
    Gson Gson=new GsonBuilder().serializeNulls().create()
    。这不起作用,因为它序列化了所有空值

  • 使用
    TypeAdapterFactory
    。这几乎可以正常工作,但我找不到一种方法来重用Gson的默认
    MapTypeAdapter
    ,将其与
    serializeNulls=true
    的序列化上下文一起使用
    MapTypeAdapter
    final
    ,因此我无法将其子类化。我不想从头开始编写
    TypeAdapter
    来序列化映射


我觉得有一个简单的解决方案我错过了。非常感谢您的帮助。

您需要注意,我们可以直接在
com.google.gson.stream.JsonWriter
实例上设置
序列化null
功能。因此,让我们实现自定义
com.google.gson.TypeAdapterFactory
,它总是为
Map
实例强制使用此功能:

class ForceNullsForMapTypeAdapterFactory implements TypeAdapterFactory {

    public final <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
        if (Map.class.isAssignableFrom(type.getRawType())) {
            final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);
            return createCustomTypeAdapter(delegate);
        }

        return null;
    }

    private <T> TypeAdapter<T> createCustomTypeAdapter(TypeAdapter<T> delegate) {
        return new TypeAdapter<T>() {
            @Override
            public void write(JsonWriter out, T value) throws IOException {
                final boolean serializeNulls = out.getSerializeNulls();
                try {
                    out.setSerializeNulls(true);
                    delegate.write(out, value);
                } finally {
                    out.setSerializeNulls(serializeNulls);
                }
            }

            @Override
            public T read(JsonReader in) throws IOException {
                return delegate.read(in);
            }
        };
    }
}

是否要在序列化过程中忽略
null
字段?然后试着不用这个
.serializeNulls()
太棒了,我想这正是我想要的
getDelegateAdapter()
是拼图中缺失的一块。非常感谢!
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;

import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;

public class GsonApp {
    public static void main(String[] args) {
        Map<String, Object> map = new LinkedHashMap<>();
        map.put("nullKey", null);
        map.put("other", "Not Null!");

        Foo foo = new Foo();
        foo.setMyMap(map);

        Gson gson = new GsonBuilder()
                .setPrettyPrinting()
                .registerTypeAdapterFactory(new ForceNullsForMapTypeAdapterFactory())
                .create();
        System.out.println(gson.toJson(foo));
    }
}
{
  "my_map": {
    "nullKey": null,
    "other": "Not Null!"
  }
}