我正在使用Gson反序列化一堆对象,其中一些更复杂,一些“轻量级”。
我在这里遇到了一个难题,因为我一直在期待GSON.fromJson()在阅读一个值为null
的字段时会有另一个行为。更准确地说,看看这个例子
public class TestApplication{
@Data
@NoArgsConstructor
public class User{
private String userName;
@SerializedName(value = "eMailAddress")
private String email;
private final List<Object> list = new ArrayList<>();
}
public static void main(String[] args) {
String x = "{\n" + "\"userName\": \"test\""
+ ",\n" + "\"eMailAddress\": \"dan@gmail.com\""
+ ",\n" + "\"list\": null\n"
+ "}";
User from = new Gson().fromJson(x, User.class);
System.out.println(from);
}
}
这将打印:
TestApplication.User(userName=test, email=dan@gmail.com, list=null)
我希望输出列表为空(list=[]
)而不是null。
我能做些什么来达到我需要的行为吗?我的应用程序使用对象列表,为每个对象注册一个typeAdapter是不可行的。
我该如何编写一个自定义的反序列化器?下面这个例子如果能工作的话就足够简单了:
class CollectionDeserializer implements JsonDeserializer<Collection<?>> {
public Collection<?> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return ObjectUtils.isEmpty(json) ? new ArrayList<>() : new Gson().fromJson(json, Collection.class);
}
}
我所尝试的:
- 实现客户反序列化器(如上所述),但没有成功。
- @JsonSetter(nulls= Nulls.SKIP)注解,对Gson解析没有影响。
5条答案
按热度按时间56lgkhnf1#
您的JSON字符串显式地表示此列表为null,因此我不确定您为什么首先期望它为空。对于空字符串,JSON字符串应为
[]
。然而,如果您仍然想在自定义反序列化器中将空列表转换为空列表,答案很简单。您的自定义反序列化器不工作,因为它正在测试json元素是否为null或空。两者都不是它是一个表示空元素的值。使用JsonElement.isJsonNull:
sdnqo3pr2#
它可以通过Jackson来完成,并且不显式地将该字段设置为null:
这将打印:
yzckvree3#
这可以通过自定义
TypeAdapterFactory
来解决:然后,您可以在
GsonBuilder
上注册此工厂,如下所示:使用
TypeAdapterFactory
具有以下优点:TypeAdapter
,TypeAdapter
的性能通常优于JsonDeserializer
,因为它直接对JSON流进行操作,而不必先将其转换为JsonElement
Gson
示例;反序列化将使用现有的Gson
示例及其所有配置List<MyClass>
,因为委托执行所有类型解析工作**重要提示:**您选择的任何解决方案都不会处理JSON数据中缺少字段的情况。Gson目前还不太支持这个功能,参见this feature request。当前必须使用非
null
List
显式初始化字段(并确保类具有无参数构造函数;更多信息),否则,如果JSON数据中缺少该字段,则该字段将为null
。ovfsdjhp4#
这可以通过Gson来完成,并显式地将字段设置为空列表:替换:
有:
这将打印:
ycggw6v25#
空列表与空列表不同。
如果希望所有null数组都成为空数组,则只能使用自定义适配器。工作量很大您需要以下内容:
ArrayTypeAdapter、CollectionTypeAdapterFactory和其他设置类的新变体。
更改ArrayTypeAdapter的以下行
到
我建议您不要这样做,而是添加一个输入验证器
@NotNull
,或者在反序列化之后,针对特定值以编程方式将null
更改为[]