Spring Data Elasticsearch反序列化时如何忽略null字段
问题说明
设置spring.jackson.default-property-inclusion=non_null未生效的核心原因是:
该配置仅对Spring Web层的HTTP消息转换器生效,Spring Data Elasticsearch维护了独立的序列化/反序列化组件,不会读取这个全局Jackson参数。
对应的实体定义、ES存储结构、查询代码如下:
@Document(indexName = "test_index", createIndex = false) public class ZTest { @Id private String id; private String testOne; @Transient private String testTwo; private String testThree; }
ES中存储的两条文档结构:
{ "_index" : "test_index", "_type" : "_doc", "_id" : "w0mCgYEBXSVfca67-ayl", "_score" : 1.0, "_source" : { "_class" : "com.ZTest", "testOne" : "test_one" } }, { "_index" : "test_index", "_type" : "_doc", "_id" : "xEmLgYEBXSVfca67r6wf", "_score" : 1.0, "_source" : { "_class" : "com.ZTest", "testOne" : "test_one", "testThree" : "test_three" } }
查询逻辑:
Iterable<ZTest> t = zTestRepository.findAll();

解决方法
可根据实际场景选择以下两种方案:
方案1:单实体配置(无全局侵入)
直接在实体类上添加Jackson非空包含注解,仅对当前实体生效:
import com.fasterxml.jackson.annotation.JsonInclude; @JsonInclude(JsonInclude.Include.NON_NULL) @Document(indexName = "test_index", createIndex = false) public class ZTest { // 原有属性保持不变 }
添加后Jackson在反序列化、序列化该实体时,会自动忽略值为null的字段。
注意:
testTwo字段上的@Transient是Spring Data持久层注解,作用是标记该字段不参与ES的读写持久化,和null字段过滤无关。
方案2:全局配置(对所有ES实体生效)
如果需要所有ES查询的实体都自动过滤null字段,可以自定义Spring Data Elasticsearch使用的转换器,修改其内置的ObjectMapper配置:
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter; import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter; import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; @Configuration public class EsConfig { @Bean public ElasticsearchConverter elasticsearchConverter(SimpleElasticsearchMappingContext context) { ObjectMapper esObjectMapper = Jackson2ObjectMapperBuilder.json() .serializationInclusion(JsonInclude.Include.NON_NULL) .build(); MappingElasticsearchConverter converter = new MappingElasticsearchConverter(context, esObjectMapper); converter.afterPropertiesSet(); return converter; } }
内容的提问来源于stack exchange,提问作者Abe
相关产品推荐
相关产品推荐

