• springboot自定义Json序列化返回,实现自动转换字典值


    自定义序列化
    原理
    当你使用Spring Boot的Spring Data或者Spring MVC等组件来处理JSON序列化时,Spring框架会在需要将Java对象转换为JSON字符串时调用JsonSerializer。这通常发生在控制器方法返回JSON响应时,或者在将对象保存到数据库等操作中。

    // 注册到环境中
    @Configuration
    public class CustomJsonConverterConfig {
    	@Bean
        public DictJsonSerializer serializer(ObjectMapper objectMapper) {
            final DictJsonSerializer dictJsonSerializer = new DictJsonSerializer();
            /*final BigDecimalSerializer bigDecimalSerializer = new BigDecimalSerializer();
            final DoubleSerializer doubleSerializer = new DoubleSerializer();*/
            SimpleModule simpleModule = new SimpleModule();
            simpleModule.addSerializer(BaseDictVo.class, dictJsonSerializer);
            simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
            simpleModule.addSerializer(BigInteger.class, ToStringSerializer.instance);
    //        simpleModule.addSerializer(BigDecimal.class, bigDecimalSerializer);
    //        simpleModule.addSerializer(Double.class, doubleSerializer);
            objectMapper.registerModule(simpleModule);
            return dictJsonSerializer;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    跟基础平台不同,返回的是序列化类,而不是objectMapper

    编写序列化实现类
    (注意:只有当返回对象实现了BaseDictVo才会生效,避免对所有代码进行过滤,导致性能损耗)

    public class DictJsonSerializer extends JsonSerializer<BaseDictVo> {
        /**
         * 自定义字典序列化
         *
         * @param source    字段值
         * @param generator Json 生成器
         * @param provider  Json 提供者
         * @throws IOException
         */
        @Override
        public void serialize(BaseDictVo source, JsonGenerator generator, SerializerProvider provider) throws IOException {
            // 写入JSON开头对象 {
            generator.writeStartObject();
            for (Field field : source.getClass().getDeclaredFields()) {
                final Object fieldValue = ReflectUtil.getFieldValue(source, field);
                final TransDict transDict = field.getDeclaredAnnotation(TransDict.class);
                if (Objects.isNull(fieldValue) || Objects.isNull(transDict)) {
                    if (Objects.nonNull(fieldValue)) {
                        generator.writeObjectField(field.getName(), fieldValue);
                    }
                    continue;
                }
                // 字典编码
                final String dictCode = transDict.code();
                // 转换的目标字段
                final String targetFiledName = transDict.alias();
                if (StringUtils.isBlank(dictCode)) {
                    generator.writeObjectField(field.getName(), fieldValue);
                    continue;
                }
                // 字段转换
                final List<String> strings = Arrays.asList(StringUtils.split(fieldValue.toString(), ","));
                StringBuilder dictValues = new StringBuilder();
                final Iterator<String> iterator = strings.iterator();
                while (iterator.hasNext()) {
                    String code = iterator.next();
                    String val = DictUtil.convertDict(dictCode, code);
                    if (StringUtils.isBlank(code) || StringUtils.isBlank(val)) {
                        continue;
                    }
                    dictValues.append(val);
                    if (iterator.hasNext()) {
                        dictValues.append(",");
                    }
                }
                // 目标字段存在则设置目标字段值,否则设置当前字段值
                if (StringUtils.isNotBlank(targetFiledName)) {
                    generator.writeObjectField(field.getName(), fieldValue);
                    generator.writeObjectField(targetFiledName, dictValues.toString());
                } else {
                    generator.writeObjectField(field.getName(), dictValues.toString());
                }
            }
            // 写入JSON结尾对象 }
            generator.writeEndObject();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    定义注解
    用以标记字段,获取字典的编码,以及指定的目标替换字段

    @Target({ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface TransDict {
        String code() default "";
    
    
        String alias() default "";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    定义基类
    用以标记生效的类

    public interface BaseDictVo {
    }
    
    • 1
    • 2

    使用类
    使用注解示例

    @Data
    @ApiModel("反馈项vo")
    public class CmFeedbackConfigVo implements BaseDictVo {
    
        @ApiModelProperty(value = "业务域编码(直饮水-DRINK、SUPPLY-供水)")
        @TransDict(code = "IAM_DOMAIN", alias = "businessDomainCodeValue")
        private String businessDomainCode;
    
        @ApiModelProperty(value = "业务域编码(直饮水-DRINK、SUPPLY-供水)")
        private String businessDomainCodeValue;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    效果
    每次前端发起请求时,因为RestController作用,会在返回时把结果序列化为Json,即触发自定义序列化类

  • 相关阅读:
    网站怎么防止ddos攻击,防御ddos攻击的11种方法
    #AngularJS#简介
    Java面试题(Guide)
    [构造]Complementary XOR Codeforces1750C
    Unity实现角色受到攻击后屏幕抖动的效果
    07 - 雷达发射机的主要质量指标
    行业应用之无限可能,就在亚马逊云科技re:Invent
    Vue的生命周期的详解
    解锁数据库运维秘籍:掌握AntDB-T动态共享内存,提升进程间通信效率
    包装类和泛型
  • 原文地址:https://blog.csdn.net/u013703363/article/details/133040071