Spring Boot 自定义属性注解-属性为空返回设置的默认值 jackson

作者:青山常在人不老   阅读 (4588)  |  收藏 (0)  |  点赞 (0)

摘要

我曾经写过一篇Spring boot里面使用fastJson自定义属性注解实现个性化的处理null并返回其他值的实现方式,本文讲解在jackson中如何实现通过注解自定义Null返回的值。


原文链接:Spring Boot 自定义属性注解-属性为空返回设置的默认值 jackson

本次实现的需求如下:

1、只有注解、注解只有默认值 :值为null时-Double、Integer、Float、Long:0、,Charract:'',String:"",Boolean:true,List、Map、Set:空集合

2、注解有默认值(可以包含null)和标签时:当值符合标签中的值时,返回默认值,否则返回原值

实现方式

自定义接口类

该接口中有两个字段:tags,defaultVal,分别用来设置符合的值和一旦命中符合的值,要返回的值

package com.example.demo.aop;

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

import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

/**
 * 1、tags 不填,defaultVal 填写啥就返回啥
 * 2、tags 不填,defaultVal 不填写则返回原值
 * 3、tags 填写,defaultVal 不填写则返回原值
 * 4、tags 填写,defaultVal填写,如果原值和tags中匹配,则返回defaultVal,否则返回原值
 * 5、只针对8中包装类型,其余类型属性不得使用
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
@JacksonAnnotationsInside
@JsonSerialize(using = MaskFieldSerializer.class)
//@JsonSerialize(using = MyExpressionDeserializer.class)
public @interface DefaultFieldVal {
    //哪些标签需要转换
    String [] tags() default {};
    //要转换的值
    String defaultVal() default "";
}

具体实现类:

package com.example.demo.aop;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import com.example.demo.StringUtils;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import org.assertj.core.util.Lists;
import org.springframework.util.CollectionUtils;

public class MaskFieldSerializer extends JsonSerializer<Object> implements ContextualSerializer {
    private String [] tags;

    private String defaultVal;

    // 必须要保留无参构造方法
    public MaskFieldSerializer () {
        super();
    }

    public MaskFieldSerializer(String[] tags, String defaultVal) {
        this.tags = tags;
        this.defaultVal = defaultVal;
    }

    @Override
    public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider)
            throws IOException {
        //list,值判断为空时赋值,否则返回原值
        if (value instanceof List) {
            if (value == null) {
                List tmp = new ArrayList();
                jgen.writeObject(tmp);
            } else {
                jgen.writeObject(value);
            }
            return ;
        }

        List<String> allTagList = Lists.newArrayList(tags).stream().map(e -> e).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(allTagList)) {
            if (defaultVal == null) {
                //2、tags 不填,defaultVal 不填写则返回原值
                jgen.writeObject(value);
            } else {
                //1、tags 不填,defaultVal 填写啥就返回啥
                jgen.writeObject(defaultVal);
            }
            return ;
        }

        //3、tags 填写,defaultVal 不填写则返回原值
        if (defaultVal == null) {
            jgen.writeObject(value);
            return ;
        }

        //4、tags 填写,defaultVal填写,如果原值和tags中匹配,则返回defaultVal,否则返回原值
        String tmpStr = null;
        if (value == null) {
            tmpStr = "null";
        } else {
            tmpStr = String.valueOf(value);
        }
        if (allTagList.contains(tmpStr)) {
            if (StringUtils.isNotBlank(defaultVal)) {
                jgen.writeObject(defaultVal);
            } else {
                jgen.writeObject(value);
            }
        } else {
            String currentName = jgen.getOutputContext().getCurrentName();
            System.out.println(currentName);
            jgen.writeObject(value);
        }
    }

    /**
     * 获取field的注解信息
     * @param serializerProvider provider
     * @param beanProperty 实体类的属性
     * @return
     * @throws JsonMappingException
     */
    @Override
    public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
        if (beanProperty != null) { // 为空直接跳过
            DefaultFieldVal defaultFieldVal = beanProperty.getAnnotation (DefaultFieldVal.class);
            if (defaultFieldVal == null) {
                defaultFieldVal = beanProperty.getContextAnnotation (DefaultFieldVal.class);
            }
            if (defaultFieldVal != null) { // 如果能得到注解,就将注解的 value 传入 ImageURLSerialize
                return new MaskFieldSerializer (defaultFieldVal.tags(),defaultFieldVal.defaultVal());
            }
        }
        return serializerProvider.findValueSerializer (beanProperty.getType (), beanProperty);
    }
}

上面两个类即可实现上述业务需求。

下面是测试类

测试

测试实体类

package com.example.demo.entity;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

import com.example.demo.aop.DefaultFieldVal;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

@Data
public class TestResponse {

    @DefaultFieldVal(tags = {"李四"} , defaultVal = "测试为李四的默认值")
    private String name;

    @DefaultFieldVal(tags = {"null","sds"} , defaultVal = "测试为值")
    private String fullName;

    @JsonProperty("Addr")
    @DefaultFieldVal(tags = {"aaa","null"} , defaultVal = "测试变化")
    private String addr;

    @DefaultFieldVal(tags = {"1","2"} , defaultVal = "小孩子")
    private Integer age;

    @DefaultFieldVal(defaultVal = "男士")
    private Boolean isMen;

    @DefaultFieldVal(tags = {"null"} , defaultVal = "true")
    private Boolean exists;

    @DefaultFieldVal(defaultVal = "99.9")
    private Double scode;

    @DefaultFieldVal(tags = {"true", "false"} , defaultVal = "true")
    private Boolean userStatus;

    @DefaultFieldVal(tags = {"221.1"} , defaultVal = "32.9")
    private BigDecimal price;

    @DefaultFieldVal
    private List<Integer> aaList;

    @DefaultFieldVal( defaultVal = "2021-23-22")
    private Date currentDate;

}

Controller类

package com.example.demo.controller;

import com.example.demo.entity.TestResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping(value = "/test")
public class TestJsonDefaultController {

    @RequestMapping(value = "/getDealerLicense")
    @ResponseBody
    public TestResponse getDealerLicense(String name,String fullName) {
        TestResponse testResponse = new TestResponse();
        testResponse.setName(name);
        testResponse.setFullName(fullName);
        testResponse.setAddr("aaa");
        testResponse.setAge(12);
        testResponse.setIsMen(null);
        testResponse.setExists(true);
        testResponse.setCurrentDate(null);
        return testResponse;
    }
}

通过上述代码就能实现上述业务。

注意:这只是一个技巧和方式,能实现业务,但是里面有部分逻辑问题,具体实现请自己斟酌后再加入到自己的项目中,。

分类   项目开发逻辑
字数   6636

博客标签    jackjson 自定义属性注解  

评论