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;
相关推荐
8***848212 分钟前
spring security 超详细使用教程(接入springboot、前后端分离)
java·spring boot·spring
9***J62815 分钟前
Spring Boot项目集成Redisson 原始依赖与 Spring Boot Starter 的流程
java·spring boot·后端
M***Z21026 分钟前
SQL 建表语句详解
java·数据库·sql
v***79426 分钟前
Spring Boot 热部署
java·spring boot·后端
执笔论英雄27 分钟前
【RL】python协程
java·网络·人工智能·python·设计模式
galaxyffang38 分钟前
认证、会话管理、授权的区别
java
未名编程41 分钟前
Windows 下如何部署 Nacos 并导入配置文件
java·windows
boonya1 小时前
Java中Plugin设计模式的规范应用
java·spring·设计模式·插件模式
杰克尼1 小时前
3. 分巧克力
java·数据结构·算法
听风吟丶1 小时前
Java 高级多线程编程:从虚拟线程到结构化并发的实战演进
java·开发语言