使用 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 和容器可能嵌套得很深。
我尝试了以下方法:
使用 Gson gson = new GsonBuilder().serializeNulls().create()
。这不起作用,因为它序列化了所有空值。
使用 TypeAdapterFactory
。这几乎可行,但我找不到一种方法来重用 Gson 的默认 MapTypeAdapter
和 serializeNulls = true
的序列化上下文。 MapTypeAdapter
是 final
所以我不能 subclass 它。我不想从头开始写 TypeAdapter
来序列化地图。
我觉得我缺少一个简单的解决方案。任何帮助表示赞赏。
您需要注意 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!"
}
}
使用 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 和容器可能嵌套得很深。
我尝试了以下方法:
使用
Gson gson = new GsonBuilder().serializeNulls().create()
。这不起作用,因为它序列化了所有空值。使用
TypeAdapterFactory
。这几乎可行,但我找不到一种方法来重用 Gson 的默认MapTypeAdapter
和serializeNulls = true
的序列化上下文。MapTypeAdapter
是final
所以我不能 subclass 它。我不想从头开始写TypeAdapter
来序列化地图。
我觉得我缺少一个简单的解决方案。任何帮助表示赞赏。
您需要注意 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!"
}
}