使用 Gson,我如何序列化地图中的空值而不是其他 类?

Using Gson, how can I serialize nulls in maps but not in other classes?

使用 Gson,我希望能够在 Map 中序列化空值,但不能在其他 class 中序列化。即,如果我有这样的 class:

public class Foo {
  @SerializedName("bar")
  Bar bar;

  @SerializedName("my_map")
  Map<String, Object> myMap;
}

如果 bar 字段为空且 myMap 包含一个条目 "key" -> null,我希望生成的 JSON 字符串为:

{
  "my_map": {
    "key": null,
  }
}

但是,我需要它以一种非常通用的方式工作:我有很多具有复杂层次结构的 classes,并且 classes 和容器可能嵌套得很深。

我尝试了以下方法:

我觉得我缺少一个简单的解决方案。任何帮助表示赞赏。

您需要注意 SerializeNulls 功能我们可以直接在 com.google.gson.stream.JsonWriter 实例上设置。因此,让我们实现自定义 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);
            }
        };
    }
}

简单用法:

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!"
  }
}