1.简述

2.返回为空的场景及其处理方案

     2.1返回空对象或是空集合处理方案      2.2对于返回data为集合类型,data中有对象为空的处理方案
         2.2.1更改序列化规则(三种方式)
         2.2.2指定空对象上添加注解



1.简述



    springMVC返回前端数据格式应该想到HttpMessageConverter,简单来讲就是将http请求的请求内容和响应内容转化为对应格式.常见的http消息转化器有很多,现在大部分前后端数据通用格式为json,和json处理相关内的消息转化器是

MappingJacksonHttpMessageConverter: 负责读取和写入json格式的数据;具体实现方式本文以 jackson进行说明,也是springMVC默认支持的处理json的方式.里面涉及几个类(下面处理会用到简单提一下):


    ObjectMapper,支持json格式信息读取;


    SerializationFeature:序列化规定的特性或是叫做规则更容易理解,不同规则会有相应的处理.


案例场景用到的响应封装参数:

public class ResultVo<T>  {

    private int code;

    // 是否成功标识.true表示成功,false表示失败
    private boolean success;

    // 操作成功时需要响应给客户端的响应数据
    private String msg;

    private T data;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    private Date time;
// 省略get/set
    }

以下所有的返回信息均以data为目标进行处理


2.返回为空的场景及其处理方案




2.1返回空对象或是空集合处理方案


    直接new HashMap<>()或是ArrayList<>(),适用于前端接仅接收一个空对象或是空集合场景.
相关代码如下:

@RequestMapping("/test")
@RestController
public class TestJsonkon {

    @GetMapping("/test")
    public ResultVo commonDdos(){
        return ResultVoUtil.success(new HashMap<>());
    }

  }

返回信息:

springboot返回图片给前端 springboot返回对象_开发语言



2.2对于返回data为集合类型,data中有对象为空的处理方案



    这里创建两个对象,业务场景是要求返回的集合中有数据的要返回具体的数据信息,没有数据的要返回空对象.不理解业务场景没关系,可以直接关注空对象CommonDto2 即可.


前后端返回协议:


springboot返回图片给前端 springboot返回对象_springboot返回图片给前端_02

相关代码:
公共父类

public class CommonDdo  {
}

返回子对象1

public class CommonDto1 extends CommonDdo {
    private String name;
    private int age;

   // 省略get/set
}

返回子对象2

public class CommonDto2 extends CommonDdo {
}

测试代码:

@RequestMapping("/test")
@RestController
public class TestJsonkon {

    @GetMapping("/test")
    public ResultVo<ArrayList<CommonDdo>> commonDdos(){
        ArrayList<CommonDdo> commonDdos = new ArrayList<>();
        commonDdos.add(new CommonDto1("jack",18));
        commonDdos.add(new CommonDto2());
        commonDdos.add(new CommonDto2());
        return ResultVoUtil.success(commonDdos);
    }

进行测试发现:

org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class com.chenghao.program.chenghaoprogram.jacksonHandle.CommonDto2]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class com.chenghao.program.chenghaoprogram.jacksonHandle.CommonDto2 and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: com.chenghao.program.chenghaoprogram.interceptorHanle.ResultVo["data"]->java.util.ArrayList[1])
	at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:460) ~[spring-web-5.3.8.jar:5.3.8]
	// 省略部分异常...
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class com.chenghao.program.chenghaoprogram.jacksonHandle.CommonDto2 and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: com.chenghao.program.chenghaoprogram.interceptorHanle.ResultVo["data"]->java.util.ArrayList[1])
	at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77) ~[jackson-databind-2.12.3.jar:2.12.3]
	at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1276) ~[jackson-databind-2.12.3.jar:2.12.3]
	at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:400) ~[jackson-databind-2.12.3.jar:2.12.3]
	at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:71) ~[jackson-databind-2.12.3.jar:2.12.3]
	at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:33) ~[jackson-databind-2.12.3.jar:2.12.3]
	// 省略部分异常
	... 48 common frames omitted

最根本的异常信息:com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class com.chenghao.program.chenghaoprogram.jacksonHandle.CommonDto2 and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: com.chenghao.program.chenghaoprogram.interceptorHanle.ResultVo["data"]->java.util.ArrayList[1]) 关键原因分析:SerializationFeature.FAIL_ON_EMPTY_BEANS,这是序列化规则中的一种,具体实现:

/**
	确定在找不到类型的访问器时会发生什么的功能(并且没有注释表明它是要序列化的)。如果启用(默认),则抛出异常以指示这些为不可序列化的类型;如果禁用,它们将被序列化为空对象,即没有任何属性。
请注意,此功能仅对那些没有任何可识别注释(如@JsonSerialize)的“空”bean 起作用的空类型:具有注释的那些不会导致抛出异常。

默认情况下启用该功能。
 */
FAIL_ON_EMPTY_BEANS(true),

也就是说对于默认空对象,序列化特性(规则)中是不支持序列化,代码中体现就是抛出异常.解决问题的方式有两种,更改枚举属性为false;另一中是按照注释上所讲,在指定对象上添加可识别’'空对象"的注解.


2.2.1更改序列化规则(三种方式)


1.通过自定义创建objectMapper,设置FAIL_ON_EMPTY_BEANS,相当于是覆盖默认配置.

@Bean
    public ObjectMapper getObjectMapper(){
        ObjectMapper objectMapper = new ObjectMapper();        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS,false);
        return objectMapper;
    }

2.通过Jackson2ObjectMapperFactoryBean设置

@Bean
public Jackson2ObjectMapperFactoryBean getJackson2ObjectMapperFactoryBean(){
    Jackson2ObjectMapperFactoryBean jackson2ObjectMapperFactoryBean = new Jackson2ObjectMapperFactoryBean();
    jackson2ObjectMapperFactoryBean.setFailOnEmptyBeans(false);
    return jackson2ObjectMapperFactoryBean;
}

3.通过配置文件

spring:
  jackson:
    serialization:
      FAIL_ON_EMPTY_BEANS: false



2.2.2指定空对象上添加注解


自定义定义空对象类上添加注解:@JsonInclude(JsonInclude.Include.NON_EMPTY)
    该注解可以作用于类上表示为空对象对象时不参与序列化.平常常用的方式是作用于实体类字段属性上,当为空时不返回前端数据.
    以上处理均自测完成,如有问题欢迎评论区留言讨论!