3

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

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

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

这是我正在谈论的示例:

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)时才返回 true 。nullnullabsent

@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)并排除简单“缺失”的字段,我使用@JsonInclude(Include.NON_EMPTY) annotation.

4

1 回答 1

2

不幸的是,查看serializer 的源代码,我看不到有一种开箱即用的方式来做你正在寻找的事情。 Optional.absent()只是委托给默认的空处理行为,这将尊重@JsonInclude注释。

这是合理的,因为整个动机Optional<>是您不应该分配nullOptional<>参考。

但是,您始终可以编写自己的序列化程序来为您执行此操作。实现很像 linked 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
    }
}
于 2014-08-11T00:16:36.433 回答