Jackson和Guava数据类型模块:忽略缺少的字段,但序列化显式空值

时间:2014-08-10 21:22:42

标签: java json jackson guava jackson-modules

我在json中存储RESTful端点的测试数据。我将测试数据反序列化为POJO以传递给REST Assured进行测试。在引擎盖下,REST Assured在构造请求对象时使用Jackson序列化POJO。

我使用Guava数据类型模块来区分json中存在但设置为null的字段和根本不存在的字段。当json使用带有可选字段的guava数据类型模块的jackson反序列化为POJO时,json中缺少的字段在POJO中设置为null,而json中存在的值显式为null的字段设置为null到Optional.absent()。

当Rest Assured(在杰克逊的帮助下)将POJO序列化以构建HTTP Reguest对象时,我希望'缺少'要忽略的字段(在POJO中为null),但是那些存在的字段,但显式设置为null(POJO中的Optional.absent())要序列化。我不能使用@JsonInclude(Include.NON_NULL)注释,因为它排除了两种情况,因为Guava数据类型模块中的Guava数据类型的Serializer处理它们的方式。我想要一种方法来覆盖这种行为,同时保留我使用该模块的能力。我不确定该怎么做。

以下是我所谈论的例子:

public class Item {
    private Optional<Integer> id;
    private Optional<String> name;
    private Optional<String> description;
}

{ "name":null, "description":"Something" }

一旦上面的json String被反序列化,上面的POJO将被实例化:

Item: 
    id = null 
    name = Optional.<String>absent()
    description = "Something"

当POJO序列化回json时,我希望输出与测试数据中的输出相同:

{ "name":null, "description":"Something" }

然而,我得到的是:

{ "id":null, "name":null, "description":"Something" }

如果我使用@JsonInclude(Include.NON_NULL),我明白了:

{ "description":"Something" }

更新:

所以,我基本上攻击了模块来做我想做的事情。以下是我做的改动:

GuavaOptionalSerializer中,我将isEmpty(Optional<?> value)更改为仅在值为null时才返回true,而不是nullabsent

@Override
public boolean isEmpty(Optional<?> value) {
    return (value == null);
}

GuavaOptionalBeanPropertyWriter中,我将serializeAsField方法更改为首先处理抑制空值,然后处理null值:

@Override
public void serializeAsField(Object bean, JsonGenerator jgen, SerializerProvider prov) throws Exception
{                   
    // and then see if we must suppress certain values (default, empty)
    if (_suppressableValue != null) {       
        super.serializeAsField(bean, jgen, prov);
        return;
    }

    if (_nullSerializer == null) {
        Object value = get(bean);   
        if (Optional.absent().equals(value)) {
             return;
         }      
    }

    super.serializeAsField(bean, jgen, prov);
}

现在,如果我想要包含absent字段(明确设置为null)并排除简单&#39;缺少的字段,我会使用{{1} }。

1 个答案:

答案 0 :(得分:2)

不幸的是,看着the source for the serializer,我并没有看到有一种开箱即用的方式去做你正在寻找的东西。 Optional.absent()只委托默认的空值处理行为,这将遵循@JsonInclude注释。

这是合理的,因为Optional<>的整体动机是不应null分配给Optional<>引用。

但是,您始终可以编写自己的序列化程序来为您执行此操作。实现与链接GuavaOptionalSerializer非常相似,但您需要更改此功能:

@Override
public void serialize(Optional<?> value, JsonGenerator jgen, SerializerProvider provider)
        throws IOException, JsonGenerationException {
    if(value.isPresent()){
        provider.defaultSerializeValue(value.get(), jgen);
    } else{
        // provider.defaultSerializeNull(jgen);
        // force writing null here instead of using default
    }
}