解决一个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则是我们自定义处理空字符串转换为空集合的反序列化器

相关推荐
Anastasiozzzz14 分钟前
Java Lambda 揭秘:从匿名内部类到底层原理的深度解析
java·开发语言
骇客野人15 分钟前
通过脚本推送Docker镜像
java·docker·容器
韩立学长31 分钟前
基于Springboot泉州旅游攻略平台d5h5zz02(程序、源码、数据库、调试部署方案及开发环境)系统界面展示及获取方式置于文档末尾,可供参考。
数据库·spring boot·旅游
铁蛋AI编程实战32 分钟前
通义千问 3.5 Turbo GGUF 量化版本地部署教程:4G 显存即可运行,数据永不泄露
java·人工智能·python
晚霞的不甘43 分钟前
CANN 编译器深度解析:UB、L1 与 Global Memory 的协同调度机制
java·后端·spring·架构·音视频
SunnyDays10111 小时前
使用 Java 冻结 Excel 行和列:完整指南
java·冻结excel行和列
摇滚侠1 小时前
在 SpringBoot 项目中,开发工具使用 IDEA,.idea 目录下的文件需要提交吗
java·spring boot·intellij-idea
云姜.1 小时前
java多态
java·开发语言·c++
李堇1 小时前
android滚动列表VerticalRollingTextView
android·java
泉-java1 小时前
第56条:为所有导出的API元素编写文档注释 《Effective Java》
java·开发语言