响应体空值处理

David 2022-09-28 23:50:30
Categories: Tags:
  • 当请求接口不返回数据时,封装后响应体传递的 JSON 数据中 data 的值就会显示为 null,整体上看起来并不协调,我们可以对 data 的空值进行处理,转化为空符串

 

 

  • 我们可以自定义一个 Jackson 配置类,在配置类中使用 Jackson2ObjectMapperBuilder 来建一个 ObjectMapper 用于获取当前 ObjectMapper实例的序列化对象,然后将序列化时为 null 值实例化一个新的 JsonSerializer 类用于写入为空字符串

示例

@Configuration

public class JacksonConfig {

    @Bean

    @Primary

    @ConditionalOnMissingBean(ObjectMapper.class)

    public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {

        ObjectMapper objectMapper = builder.createXmlMapper(false).build();

        objectMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {

            @Override

            public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {

                jsonGenerator.writeString("");

            }

        });

        return objectMapper;

    }

}

 

 

 

类型空处理

  • 虽然将 null 值显示为空字符串协调了响应体,但是仍然没解决数据应该根据类型显示的问题。正常情况下,我们应该能够根据 JSON 中的数据格式大致判断出属性的数据类型,而不是统一处理为空字符。

 

 

类型

默认返回值

String

""

Boolean

false

Integer

Float

Double

BigDecimal

Long

Short

0

Array

List

Set

[]

Date

null

 

  • 我们可以前面的基础上,在JsonSerializer.serialize 方法中通过反射获取数据类型,根据数据类型再对特定数据类型的处理

示例

@Configuration

public class JacksonConfig {

    @Bean

    @Primary

    @ConditionalOnMissingBean(ObjectMapper.class)

    public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {

        ObjectMapper objectMapper = builder.createXmlMapper(false).build();

        objectMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {

            @Override

            public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {

                String fieldName = jsonGenerator.getOutputContext().getCurrentName();

                //反射获取字段

                Class<?> currentClass = jsonGenerator.getCurrentValue().getClass();

                Field field = ReflectionUtils.findField(currentClass, fieldName);

                System.out.println(field.getType());

                //判断空值

                if (ObjectUtils.isNull(field)) {

                    return;

                }

                //String类型返回""

                if (Objects.equals(field.getType(), String.class)) {

                    jsonGenerator.writeString("");

                    return;

                }

                //Boolean类型返回false

                if (Objects.equals(field.getType(), Boolean.class)) {

                    jsonGenerator.writeBoolean(false);

                    return;

                }

                // 数字类型IntegerFloatDoubleBigDecimalLongShort等类型返回0

                if (Number.class.isAssignableFrom(field.getType())) {

                    jsonGenerator.writeNumber(0);

                    return;

                }

                //ArrayListSet类型返回[]

                if (field.getType().isArray() || Collection.class.isAssignableFrom(field.getType())) {

                    jsonGenerator.writeStartArray();

                    jsonGenerator.writeEndArray();

                    return;

                }

                //Date类型返回null

                if (Date.class.isAssignableFrom(field.getType()) || LocalDateTime.class.isAssignableFrom(field.getType()) || 

                    LocalDate.class.isAssignableFrom(field.getType()) || LocalTime.class.isAssignableFrom(field.getType())) {

                    jsonGenerator.writeNull();

                    return;

                }

 

                //其他Object返回{}

                jsonGenerator.writeStartObject();

                jsonGenerator.writeEndObject();

            }

        });

        return objectMapper;

    }

}

 

 

空值屏蔽

  • 当业务逻辑和异常处理足够完整时,我们还可以直接排除对 data null 情况下的序列化显示

 

 

  • 对空值取消序列化在 SpringBoot 中有两种方法
    1. 使用注解(@JsonInclude
    2. Jackson 全局配置(spring.jackson.default-property-inclusion

 

  • @JsonInclude 是一个 Jackson 库的注解,用于指定在序列化 Java 对象为 JSON 格式时应包含哪些属性。我们可以通过设置 JsonInclude.Include.NON_NULL 排除对空值的序列化

示例

@Data

@NoArgsConstructor

@JsonInclude(JsonInclude.Include.NON_NULL)

public class Result<T> {

    private int code;

    private T data;

    private String msg;

 

    public Result(T data) {

        this.code = ResultCode.SUCCESS.getCode();

        this.data = data;

        this.msg = ResultCode.SUCCESS.getMsg();

    }

 

    public Result(ResultCode resultCode, T data) {

        this.code = resultCode.getCode();

        this.data = data;

        this.msg = resultCode.getMsg();

    }

 

    public static <T> Result<T> success(T data) {

        return new Result<>(ResultCode.SUCCESS, data);

    }

}

 

  • Jackson 配置中允许自定义包含的参数类型,我们只需要在 application.xml 全局配置中设置 spring.jackson.default-property-inclusion 的参数值为 non_null ,这种方法会作用到全局,因此并不推荐使用

示例

spring.jackson.default-property-inclusion: non_null

空值排除建议在数据处理相对完整的情况下使用,否则在返回数据为空时会缺少 data 属性,降低数据判断的准确性