解决一个JSON反序列化问题-空字符串变为空集合

解决一个JSON反序列化问题-空字符串变为空集合

1.问题场景

当我后端实体中定义如下:

java 复制代码
private List<String> projectTypeId;

如果前端传projectTypeId 是 null 或者 \[\] 都是没问题的。当前端传"" 则会报错。 报错如下:

java 复制代码
Caused by: com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot coerce empty String ("") to element of `java.util.ArrayList<java.lang.String>` (but could if coercion was enabled using `CoercionConfig`)
 at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 8, column: 22] (through reference chain: com.safesoft.web.landProject.vo.LandProjectQueryVO["projectTypeId"])

意思是无法将空字符串强转为集合

2.解决办法(前端)

前端把"" 变为null或者\[\]即可

(但是我所在这个项目,原先定义的是 private String projectTypeId; 前端传"" 也没毛病,但是后期更改需求,需要变成集合。但是前端每个人写的语法不一样,上个前端人员如果是null则传的"" 。因此造成这个bug)

3.解决办法(后端)

3.1 编写一个自定义 JSON 反序列化器 EmptyStringListDeserializer

java 复制代码
package com.safesoft.common.config;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 自定义 JSON 反序列化器,用于处理空字符串在 List 中的情况。
 * 该反序列化器设计用于与 Java 类中的 `@JsonDeserialize` 注解一起使用,该注解放在 List<String> 字段上。
 * @author Kevin.Wan
 * @date 2023/12/15
 **/
public class EmptyStringListDeserializer extends JsonDeserializer<List<String>> {

    /**
     * 反序列化 JSON 数组,处理空字符串并将其转换为空列表。
     *
     * @param p      JSON 解析器。
     * @param ctxt   反序列化上下文。
     * @return 包含反序列化字符串的 List<String>。
     * @throws IOException 如果在反序列化过程中发生 I/O 错误。
     */
    @Override
    public List<String> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        // 读取整个 JSON 节点
        JsonNode node = p.readValueAsTree();
        // 检查节点是否为 null、缺失或不是数组
        if (node == null || node.isNull() || node.isMissingNode() || !node.isArray()) {
            // 对于 null、缺失或非数组情况,返回空列表
            return new ArrayList<>();
        } else {
            // 处理数组中的每个元素
            List<String> values = new ArrayList<>();
            for (JsonNode element : node) {
                // 检查元素是否为文本节点
                if (element.isTextual()) {
                    // 将文本值添加到列表中
                    values.add(element.textValue());
                }
            }
            // 返回反序列化字符串的列表
            return values;
        }
    }
}

3.2 然后在可能存在空字符串转换集合的实体上 添加注解

java 复制代码
/**
 * 项目类型id
 */
@JsonDeserialize(using = EmptyStringListDeserializer.class)
private List<String> projectTypeId;

@JsonDeserialize

是在反序列化时,所以就是对参数进行封装,故到的是 setXxxx() 方法,所以需要将注解添加到对应的 set 方法上,若使用了 Lombok 需要自己定义相应的 set 方法。

需要使用 using 属性指定处理参数的类,该类需要继承 JsonDeserializer 类,并重写 deserialize()。

自己见解:

@JsonDeserialize是String提供的反序列化注解,其中 using可以自定义一个反序列化,EmptyStringListDeserializer则是我们自定义处理空字符串转换为空集合的反序列化器

相关推荐
mldong5 小时前
引擎从不发一条消息:jeeflow 的两类扩展点与消息模块的分工
java·架构
君顾15 小时前
智慧零售实战指南:从技术架构到落地方案全解析
java·开发语言·零售
zhanghe6876 小时前
es的密码带有特殊字符,导出
java
pnoker6 小时前
IoT DC3 概念解读:把设备抽象成一套语义模板——位号、指令、事件与面向智能体的设备建模
java·人工智能·物联网·iot·dc3
my_realmy6 小时前
Java SE 基础学习笔记(一):面向对象、继承多态、抽象接口与异常(JDK 8)
java·多线程·并发··生产者消费者模式
天远数科7 小时前
风险治理实战:基于天远车信盟出险构建自动化理赔核保流水线
java·网络·人工智能·自动化
步行cgn7 小时前
YAML 的语法规则
spring boot·后端
骇客野人7 小时前
SpringBoot电商系统用户注册、登录、留存及数据埋点设计与落地实施方案
java·spring boot·后端
摇滚侠7 小时前
《SpringBoot 3:入门与应用实战》第 12 章 JDBC 与事务 数据库初始化机制 阅读笔记 36
数据库·spring boot·笔记
qiuhaipeng17 小时前
Claude code 升级后上下文长度变短问题
java·前端·数据库