easy-es Map类型字段序列化问题:Unexpected character (‘n‘ (code 110)):

java 复制代码
@Data
@IndexName("demo")
public class EasyEsDemo {

    @IndexId
    private String id;

    private String name;
    private int age;

    // 这个Map字段因为NameFilter过滤器,导致fastjson序列化后为{null:"value"}这种形式,insert报错
    private Map<String, Object> data;
}

上面Map类型字段保存报错如下:

java 复制代码
Caused by: ElasticsearchException[Elasticsearch exception [type=json_parse_exception, reason=Unexpected character ('n' (code 110)): was expecting double-quote to start field name
.....

此错误主要原因是:EntityInfoHelper中创建的NameFilter是一个匿名类,看上去主要功能就是过滤排除字段,但是针对Map类型字段就出现了问题,导致序列化时候Map的key字段变成了个null. 导致fastjson序列化后为{null:"value"}这种形式,insert报错。

EntityInfoHelper中NameFilter过滤器代码如下:这个过滤器导致序列化Map类型字段时,获取的key当成类的字段属性处理,而类中没有名字为key的字段,所以过滤器过滤完后key变成了null

java 复制代码
    /**
     * 添加fastjson字段过滤器
     *
     * @param entityInfo 实体信息
     */
    private static void addNameFilter(EntityInfo entityInfo, List<SerializeFilter> preFilters) {
        Map<String, String> mappingColumnMap = entityInfo.getMappingColumnMap();
        Map<Class<?>, Map<String, String>> nestedClassMappingColumnMap = entityInfo.getNestedClassMappingColumnMap();
        if (!mappingColumnMap.isEmpty()) {
            NameFilter nameFilter = (object, name, value) -> {
                Map<String, String> nestedMappingColumnMap = nestedClassMappingColumnMap.get(object.getClass());
                if (Objects.nonNull(nestedMappingColumnMap)) {
                    String nestedMappingColumn = nestedMappingColumnMap.get(name);
                    if (Objects.equals(nestedMappingColumn, name)) {
                        return name;
                    } else {
                        return nestedMappingColumn;
                    }
                }
                String mappingColumn = mappingColumnMap.get(name);
                if (Objects.equals(mappingColumn, name)) {
                    return name;
                }
                return mappingColumn;
            };
            preFilters.add(nameFilter);
        }
    }

不知道是个bug还是不推荐使用Map类型字段。或者说有别的处理方式。目前使用的处理方式如下:自定义一个Map的序列化器,并在Map类型字段增加注解

java 复制代码
    public static class MyMapSerializer extends MapSerializer {
        @Override
        protected String processKey(JSONSerializer jsonBeanDeser, Object object, String key, Object propertyValue) {
           // 删除了 jsonBeanDeser.nameFilters 的处理逻辑

            if (this.nameFilters != null) {
                for (NameFilter nameFilter : this.nameFilters) {
                    key = nameFilter.process(object, key, propertyValue);
                }
            }
            return key;
        }
    }


    // 手动指定自定义的序列化处理器

    @JSONField(serializeUsing = MyMapSerializer.class)
    private Map<String, Object> data;
相关推荐
Jabes.yang3 小时前
Java面试实录:AIGC场景下的Stream、微服务、Redis、Kafka与安全实战
java·spring boot·redis·微服务·面试·kafka·aigc
lwf0061643 小时前
实战:用 Java 模拟登录阿里云控制台,爬取没有 OpenAPI 的数据
java·阿里云
程序员二叉4 小时前
【Java】 面试核心合集:BigDecimal、缓存池、多态、反射全解析
java·缓存·面试
Full Stack Developme4 小时前
SpringMVC multipart 文件上传
java·开发语言
汪小哥4 小时前
Elasticsearch Preference + Slice 加速查询实战案例
elasticsearch
西凉的悲伤4 小时前
Spring Security + JWT 登录认证完整实践指南
java·后端·spring·spring security·jwt
晚笙coding4 小时前
从零讲透 LangChain 输出格式化:让模型真的“能用”
java·开发语言·langchain
奋斗的小方4 小时前
Java进阶篇1-1:异常
java·开发语言·python
码语智行4 小时前
行政区划 ZIP 导入(importZip)
java
何中应4 小时前
Nexus如何设置端口号
java·服务器·maven·nexus