我有一个pojo类型,需要在序列化时将特定数值设置为特殊字符串。这些值将始终为null,可能非常深入到层次结构中。
为了实现这一点,我首先将pojo转换为JsonNode,其中null保持不变以保留属性顺序,然后我按照结构中的路径设置一些字符串并根据需要创建节点。最后,我让ObjectMapper将JsonNode序列化为一个字符串。逻辑看起来像这样:
ObjectMapper nonNullMapper = new ObjectMapper();
nonNullMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
ObjectMapper includeAllMapper = new ObjectMapper();
includeAllMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
// NullNodes create stubs to maintain property order
JsonNode node = includeAllMapper.valueToTree(pojoInstance);
insertStrings(node);
String json = nonNullMapper.writeValueAsString(node);
// Halp, there's still nulls
请注意,我知道有一个@JsonInclude
注释,所以我实际上并不需要两个映射器,但事实证明我想在其他地方序列化没有空值的pojo实例,所以我不能使用它据我所知。
无论如何,我怎样才能避免将NullNodes序列化为我的json字符串?到目前为止,我找到了两种方法:
SerializationFeature.WRITE_NULL_MAP_VALUES
。这似乎效率低,而且很容易。我尝试为JsonSerializer
注册NullNode
,但似乎没有被使用。我注意到NullNode
本身实现了JsonSerializable
,它只是委托给SerializerProvider
的空值序列化程序。我犹豫是否试图覆盖这个,我觉得应该在序列化值之前进行空过滤,但我没有深入挖掘以确切了解它是如何工作的。
有更好的方法吗?
答案 0 :(得分:2)
我不知道一个好的解决方案,但我想我指出JSON树模型(JsonNode
)用于呈现精确的JSON结构;因此,应用了很少的用于过滤或变换的一般特征。它与WYSIWYG非常接近。
因此,我可能只是遍历树并明确修剪NullNode
。试图配置Jackson本身来做到这一点最终会比明确删除节点更多的工作。
答案 1 :(得分:2)
继@ StaxMan的回答,这里有一些修剪NullNodes的代码:
public static void stripNulls(JsonNode node) {
Iterator<JsonNode> it = node.iterator();
while (it.hasNext()) {
JsonNode child = it.next();
if (child.isNull())
it.remove();
else
stripNulls(child);
}
}
答案 2 :(得分:1)
我猜你的问题是由于你试图获得已经序列化的对象的String
值。
当您没有序列化任何内容时,setSerializationInclusion
参数应该做什么(因为您已经使用不同的ObjectMapper
对其进行了序列化)?
您可能会尝试使这些字段变得特别(扩展为Integer的非常简单的POJO),并为它们创建自定义转换器,当它们为空时返回所需的值。
请参阅objectMapper.registerModule
。您只需要为您创建的新特殊对象类型创建SimpleModule
和一些JsonSerializer
。它们可能非常简单:
public class SpecialOverriddenNumberSerializer
extends JsonSerializer<SpecialOverriddenNumber>
{
private final static String ILLEGAL_VALUE_TEXT = "Some text";
@Override
public void serialize (
SpecialOverriddenNumber value,
JsonGenerator jgen,
SerializerProvider provider )
throws IOException, JsonProcessingException
{
// ILLEGAL_VALUE could be equivalent to Integer.MAX_VALUE or something
// (possibly even null -- though I'm not sure if that would work well
// with the NON_NULL serialization setting)
if(value == SpecialOverriddenNumber.ILLEGAL_VALUE)
{
// jgen.writeNull();
jgen.writeString(ILLEGAL_VALUE_TEXT);
}
else
{
jgen.writeNumber(value);
}
}
}
如果您还需要反序列化器,只需创建一个JsonDeserializer
,如果它显示为null
,则会返回ILLEGAL_VALUE_TEXT
。