SpringBoot序列化、反序列化空字符串为null的三种方式

这篇具有很好参考价值的文章主要介绍了SpringBoot序列化、反序列化空字符串为null的三种方式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、需求:接收前端传入的""空字符串参数,有时候我们需要把它转为null

  • SpringBoot项目
  • 方式:①Jackson(推荐)、②切面+反射、③注解+切面+反射
  • 后两种方式,未做返回值的处理。

二、三种方式

1、Jackson正反序列化(推荐)

  • StdConverter 和 JsonSerializer的区别
两种方式都可以实现将空字符串修改为 null 值的逻辑,但它们之间有一些区别:

1. **继承的类不同**:
   - 使用 `StdConverter` 方式时,`StringToNullSerializer` 类继承自 `StdConverter<String, String>`,并实现了 `convert` 方法。
   - 使用 `JsonSerializer` 方式时,`StringToNullSerializer` 类直接继承自 `JsonSerializer<String>`,并实现了 `serialize` 方法。

2. **接口和方法不同**:
   - `StdConverter` 是 Jackson 库中提供的用于定义转换器的类,其中的 `convert` 方法用于将一个类型转换为另一个类型。
   - `JsonSerializer` 是 Jackson 库中用于定制序列化逻辑的接口,其中的 `serialize` 方法用于将 Java 对象序列化为 JSON 数据。

3. **对于序列化过程的处理不同**:
   - 在 `StdConverter` 方式中,你需要实现 `convert` 方法来定义如何将空字符串转换为 null 值。
   - 在 `JsonSerializer` 方式中,你需要实现 `serialize` 方法来定义如何将字段序列化为 JSON 数据,并在其中进行空字符串转换为 null 值的处理。

综上所述,两种方式都可以实现相同的功能,选择哪一种方式取决于个人偏好以及代码的整体结构和风格。通常来说,如果只需要定制序列化逻辑而不需要转换其他类型,直接实现 `JsonSerializer` 接口可能会更清晰和简洁。
  • ENTITY
package com.cc.jxtd.entity;

import com.cc.jxtd.serializer.ConverterEmptyStringToNull;
import com.cc.jxtd.serializer.EmptyStringToNullDeserializer;
import com.cc.jxtd.serializer.ConverterEmptyStringToInteger0;
import com.cc.jxtd.serializer.EmptyStringToNullSerializer;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.Data;

import javax.naming.Name;

/**
 * <p>请求,返回都用这个</p>
 *
 * @author --
 * @since 2024/4/19
 */
@Data
public class UserCs {

    private Long id;

    //反序列化(前端请求):空字符串为null
    @JsonDeserialize(using = EmptyStringToNullDeserializer.class)
    private String name;

    //反序列化(前端请求):转换:为其他类型的值(转换为int的0)
    @JsonDeserialize(converter = ConverterEmptyStringToInteger0.class)
    private Integer descConverter0;

    //序列化(后端返回):空字符串为null
    @JsonSerialize(using = EmptyStringToNullSerializer.class)
    private String descSerialize;

    //序列化(后端返回):转换:空字符串转为null
    @JsonSerialize(converter = ConverterEmptyStringToNull.class)
    private String descConverterNull;
    
}

  • 序列化处理类
package com.cc.jxtd.serializer;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;

import java.io.IOException;

/** 序列化:String的空转为null
 * @author --
 * @since 2024/4/18
 **/
public class EmptyStringToNullSerializer extends JsonSerializer<String> {

    /**
     * 序列化为null
     */
    @Override
    public void serialize(String value, JsonGenerator gen, SerializerProvider serializerProvider) throws IOException {
        if (value == null || value.trim().isEmpty()) {
            gen.writeNull();
        }else {
            gen.writeString(value);
        }
    }
}
  • 反序列化处理类
package com.cc.jxtd.serializer;

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

import java.io.IOException;

/** 反序列化:空字符串转换为null
 * @author --
 * @since 2024/4/18
 **/
public class EmptyStringToNullDeserializer extends JsonDeserializer<String> {

    /**
     * 反序列化为null
     */
    @Override
    public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        String value = p.getValueAsString();
        if (value == null || value.trim().isEmpty()) {
            return null;
        }
        return value;
    }

}
  • 序列化-转换1
package com.cc.jxtd.serializer;

import com.fasterxml.jackson.databind.util.StdConverter;

/** 序列化-转换:将string的空转为null
 * @author --
 * @since 2024/4/18
 **/
public class ConverterEmptyStringToNull extends StdConverter<String, String> {

    @Override
    public String convert(String value) {
        //把空的string转为int的0
        if (value == null || value.trim().isEmpty()) {
            return null;
        }
        return value;
    }

}
  • 序列化-转换2
package com.cc.jxtd.serializer;

import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.databind.util.StdConverter;

/** 序列化:1将string转为int。
 *         2转换String的空或null -》 转为Integer的0
 * @author --
 * @since 2024/4/18
 **/
public class ConverterEmptyStringToInteger0 extends StdConverter<String, Integer> {

    @Override
    public Integer convert(String value) {
        //把空的string转为int的0
        if (value == null || value.trim().isEmpty()) {
            return 0;
        }
        return Integer.valueOf(value);
    }

}
  • Controller
package com.cc.jxtd.web.controller;

import com.cc.jxtd.entity.UserCs;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * <p></p>
 *
 * @author --
 * @since 2024/4/19
 */
@RestController
@RequestMapping("/userCs")
public class UserController {

    @PostMapping
    public UserCs get(@RequestBody UserCs req){
        System.out.println("请求参数-id:"   + req.getId());
        System.out.println("请求参数-name:" + req.getName());
        System.out.println("请求参数-desc1:" + req.getDescSerialize());
        System.out.println("请求参数-desc2:" + req.getDescConverterNull());
        System.out.println("请求参数-desc3:" + req.getDescConverter0());

        //返回:序列化
        return req;
    }
}
  • 测试
    SpringBoot序列化、反序列化空字符串为null的三种方式

2、切面+反射/3、注解+切面+反射

  • 区别
2、切面+反射:所有空字符串的字段都转为null
3、注解+切面+反射:只有打了@EmptyToNull的字段才会转换
  • 导入包
		<!--spring-boot-starter-aop-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
  • 切面
package com.cc.jxtd.aspect;

import com.cc.jxtd.annotation.EmptyToNull;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.Objects;

/** 切面
 * @author --
 */
@Aspect
@Component
public class UpdateAspect {

    private static final Logger logger = LoggerFactory.getLogger(UpdateAspect.class);

    //切入点
    @Pointcut("@annotation(com.cc.jxtd.annotation.OptConverter)")
    public void validPointCut() {
    }

    /**
     * 环绕修改参数
     */
    @Around("validPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        Object[] args = point.getArgs();
        Object arg = args[0];
        //2、切面+反射:全部转换
        this.allEmptyToNull(arg);
        //3、注解+切面+反射:部分转换
//        this.assignEmptyToNull(arg);

        return point.proceed();
    }

    /**
     * 设置请求参数中 所有字段的空值(如:String的空字符串)为null
     * @param arg arg
     */
    public void allEmptyToNull(Object arg) {
        if (Objects.isNull(arg)) {
            return;
        }
        Field[] fields = arg.getClass().getDeclaredFields();
        for (Field field : fields) {
            // 设置字段可访问
            field.setAccessible(true);
            // 如果字段是 String 类型且值为空字符串,则设置为 null
            if (field.getType() == String.class) {
                try {
                    String value = (String) field.get(arg);
                    if (value != null && value.isEmpty()) {
                        field.set(arg, null);
                    }
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
            // 可以扩展其他类型的参数……

        }
    }

    /** 指定空转null
     * @param arg arg
     * @since 2024/4/18
     **/
    private void assignEmptyToNull(Object arg) {
        if (Objects.isNull(arg)) {
            return;
        }
        Field[] fields = arg.getClass().getDeclaredFields();
        for (Field field : fields) {
            if (field.isAnnotationPresent(EmptyToNull.class)) {
                // 设置字段可访问
                field.setAccessible(true);
                // 如果字段是 String 类型且值为空字符串,则设置为 null
                if (field.getType() == String.class) {
                    try {
                        String value = (String) field.get(arg);
                        if (value != null && value.isEmpty()) {
                            field.set(arg, null);
                        }
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
                // 可以扩展其他类型的参数……

            }

        }
    }
}
  • 注解
package com.cc.jxtd.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 转换
 * @author --
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OptConverter {
    
}
  • 注解2
package com.cc.jxtd.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/** 转化空为null
 * @author --
 * @since 2024/4/18
 **/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface EmptyToNull {

}
  • entity
package com.cc.jxtd.entity;

import com.cc.jxtd.serializer.ConverterEmptyStringToInteger0;
import com.cc.jxtd.serializer.ConverterEmptyStringToNull;
import com.cc.jxtd.serializer.EmptyStringToNullDeserializer;
import com.cc.jxtd.serializer.EmptyStringToNullSerializer;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.Data;

/**
 * <p>请求,返回都用这个</p>
 *
 * @author --
 * @since 2024/4/19
 */
@Data
public class UserCs2 {

    private Long id;

    private String name;

    private String desc;

}
  • controller
package com.cc.jxtd.web.controller;

import com.cc.jxtd.annotation.OptConverter;
import com.cc.jxtd.entity.UserCs;
import com.cc.jxtd.entity.UserCs2;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * <p></p>
 *
 * @author --
 * @since 2024/4/19
 */
@RestController
@RequestMapping("/userCs")
public class UserController {

//    @PostMapping
//    public UserCs get(@RequestBody UserCs req){
//        System.out.println("请求参数-id:"   + req.getId());
//        System.out.println("请求参数-name:" + req.getName());
//        System.out.println("请求参数-DescSerialize:" + req.getDescSerialize());
//        System.out.println("请求参数-DescConverterNull:" + req.getDescConverterNull());
//        System.out.println("请求参数-DescConverter0:" + req.getDescConverter0());
//
//        //返回:序列化
//        return req;
//    }

    @OptConverter
    @PostMapping
    public UserCs2 get(@RequestBody UserCs2 req){
        System.out.println("请求参数-id:"   + req.getId());
        System.out.println("请求参数-name:" + req.getName());
        System.out.println("请求参数-desc:" + req.getDesc());

        //返回:序列化
        return req;
    }

}
  • 测试2
    SpringBoot序列化、反序列化空字符串为null的三种方式

  • 测试3
    SpringBoot序列化、反序列化空字符串为null的三种方式
    SpringBoot序列化、反序列化空字符串为null的三种方式
    SpringBoot序列化、反序列化空字符串为null的三种方式文章来源地址https://www.toymoban.com/news/detail-855046.html

到了这里,关于SpringBoot序列化、反序列化空字符串为null的三种方式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • php去除字符串两边空格空字符串换行方法

    在PHP中,可以使用以下几种方法去除字符串两边的空格、空字符串和换行符: 使用trim()函数去除字符串两边的空格和空字符串,例如: 使用preg_replace()函数去除字符串中的空格、空字符串和换行符,例如:     3、使用str_replace()函数去除字符串中的空格、空字符串和换行符,

    2024年02月05日
    浏览(38)
  • fastjson2 转换别名 null变空字符串

    2024年02月02日
    浏览(28)
  • vue 对后端返回字段值为null的变成空字符串

    // 字段null转字符串 1.export function null2str(data) {     for (let x in data) {         if (data[x] === null) {             // 如果是null 把直接内容转为 \\\'\\\'             data[x] = \\\"\\\";         } else {             if (Array.isArray(data[x])) {                 // 是数组遍历数组 递归继续处理      

    2024年02月11日
    浏览(34)
  • MySQL判断列的值既不为NULL又不为空字符串

    在MySQL中,可以使用IS NULL和IS NOT NULL操作符来判断一个字符串是否为NULL,可以使用’\\\'(空字符串)或NULL与字符串进行比较来判断一个字符串是否为空。 例如,假设我们有一个名为mytable的表,其中有一个名为mycolumn的列,我们可以使用以下查询来查找mycolumn列中不为空的值:

    2024年02月11日
    浏览(35)
  • java基础08-Java中的null和空字符串的区别是什么?

    null表示一个变量没有引用任何对象,而空字符串表示一个字符串变量引用了一个长度为0的字符串。 null:表示 一个变量没有引用任何对象 。也就是说,这个变量还 没有被分配内存 。如: 如上,str是一个String类型的变量,但目前它没有被引用任何对象,所以它的值为null。

    2024年01月22日
    浏览(31)
  • 反序列化字符串逃逸(下篇)

    这里承接上篇文章反序列化字符串逃逸(上篇)-CSDN博客带大家学习反序列化字符串逃逸减少,没有看过的可以先去看看,不会吃亏。 例题: ?php highlight_file(__FILE__); error_reporting(0); function filter($name){     $safe=array(\\\"flag\\\",\\\"php\\\");     $name=str_replace($safe,\\\"hk\\\",$name);     return $

    2024年01月22日
    浏览(30)
  • springboot对象序列化自定义序列化注解

    在开发中有时候会遇到一些内容返回时需要翻译,或者一些内容在序列化之前需要特殊处理(脱敏啥的)。 一般对单个属性可以直接用 jackson 的序列化注解对某个属性单独处理 com.fasterxml.jackson.databind.annotation.JsonSerialize(using= xxx.class) 但是直接使用不太灵活,可以进一步引入注

    2024年02月07日
    浏览(39)
  • Springboot Jackson 序列化与反序列化配置

    可解决在使用默认反序列化Jackson时,LocalDateTime类型的请求参数反序列化失败的问题

    2024年02月02日
    浏览(35)
  • Json-序列化字符串时间格式问题

    最近C#中需要将实体进行json序列化,使用了Newtonsoft.Json 序列化出来的Json字符串有两个问题 1.没有进行格式化,对使用人员不友好; 2.时间字段形式为数字形式; ​​ 查了一下网上对于时间字段建议先转换成字符串,再json序列化,但是发现可以通过自定义时间格式进行json序

    2024年02月19日
    浏览(34)
  • PHP反序列化漏洞-字符串逃逸

    字符串逃逸(闭合) 字符串逃逸(闭合)是一种在反序列化函数可控的情况下,通过修改序列化字符串中的敏感字符来达到字符串逃逸的方法。 具体而言,可以通过修改变量名等个数,使得序列化字符串中的字符个数与实际变量值个数不一致 。由于反序列化机制要求字符串

    2024年01月20日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包