我有巨大的 json 文档和映射到该 json 的适当 jaskson 模型。在某些情况下,由于某些数据不存在,无法使用所有对象构建所需的 json 文档。
例如我有以下模型:
class First {
private firstField;
private secondField;
etc...
}
class Second {
private firstField;
private secondField;
etc...
}
class General {
private First first;
private Second second;
etc...
}
并且可以仅填充第一个实例:
通常情况下,它会被序列化,如下所示:
{
"first":{
"firstField":"some_value",
"secondField":"some_value"
},
"second":null
}
但我的目标是序列化 General 类,如下所示:
{
"first":{
"firstField":"some_value",
"secondField":"some_value"
},
"second":{
"firstField":"null",
"secondField":"null"
}
}
可以通过在 General 类中进行以下更改来实现此目的,以便默认使用默认构造函数初始化其成员:
class General {
private First first = new First();
private Second second = new Second()
etc...
}
但是这种方法会导致现有模型发生太多变化,我不确定这是最好的方法。是否可以创建一些自定义序列化器来自行完成此操作?
根据https://stackoverflow.com/users/1898563/michael编辑建议:
因此,主要思想是创建序列化程序,该序列化程序能够检查实例是否为空,如果为空,它应该能够使用默认构造函数创建新实例,注意:此序列化程序不应基于特定的 Second
类,它应该适用于除简单类型之外的任何要序列化的对象。
最佳答案
是的,可以创建一个使用反射来执行此操作的自定义序列化程序。您可以通过扩展StdSerializer来做到这一点。您的实现可能如下所示:
public class NullSerializer<T> extends StdSerializer<T> {
public NullSerializer() {
this(null);
}
public NullSerializer(Class<T> t) {
super(t);
}
@Override
public void serialize(T item, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonProcessingException,
IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException)
{
jgen.writeStartObject();
// For all fields of the class you're serializing
for (final Field field : item.getClass().getDeclaredFields())
{
field.setAccessible(true);
Object value = field.get(item);
// if the value is null, create a new instance
if (value == null)
{
value = field.getType().getConstructor().newInstance();
}
// write it
jgen.writeObject(value);
}
jgen.writeEndObject();
}
}
这依赖于每个字段都有一个公共(public)默认构造函数。您可能想要捕获一些异常,而不是像我所做的那样将它们声明为在签名中抛出。
您需要向 ObjectMapper 注册此序列化程序。 This article解释了如何做到这一点。
我认为这不是一个特别优雅的解决方案,但它应该满足您的要求。我首先会避免使用可为空的字段,但在您的情况下这可能是不可能的。
关于java-8 - Jackson:将空对象序列化为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45565848/