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

相关推荐
布谷歌2 分钟前
Oops! 更改field的数据类型,影响到rabbitmq消费了...(有关于Java序列化)
java·开发语言·分布式·rabbitmq·java-rabbitmq
PXM的算法星球3 分钟前
java(spring boot)实现向deepseek/GPT等模型的api发送请求/多轮对话(附源码)
java·gpt·microsoft
被程序耽误的胡先生7 分钟前
java中 kafka简单应用
java·开发语言·kafka
Long_poem10 分钟前
【自学笔记】Spring Boot框架技术基础知识点总览-持续更新
spring boot·笔记·后端
F202269748619 分钟前
Spring MVC 对象转换器:初级开发者入门指南
java·spring·mvc
楠枬40 分钟前
网页五子棋——对战后端
java·开发语言·spring boot·websocket·spring
YXWik61 小时前
23种设计模式
java·设计模式
不修×蝙蝠1 小时前
Tomcat理论(Ⅰ)
java·服务器·java-ee·tomcat
曲奇是块小饼干_1 小时前
leetcode刷题记录(一百零八)——322. 零钱兑换
java·算法·leetcode·职场和发展