Jackson 2.x 系列【31】Spring Boot 集成之字典翻译

news2025/1/12 9:04:34

有道无术,术尚可求,有术无道,止于术。

本系列Jackson 版本 2.17.0

本系列Spring Boot 版本 3.2.4

源码地址:https://gitee.com/pearl-organization/study-jaskson-demo

文章目录

    • 1. 场景描述
    • 2. 案例演示
      • 2.1 修改枚举
      • 2.2 定义注解
      • 2.3 自定义序列化器
      • 2.4 自定义装饰器
      • 2.5 配置
      • 2.6 测试

1. 场景描述

例如,用户对象中的性别字段,一般在数据库都是使用数值表示,枚举类如下:

public enum GenderEnum {

    MAN(1, "男"),

    WOMAN(2, "女");

    GenderEnum(int code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    private int code;

    private String desc;

    public static String getDesc(int code) {
        for (GenderEnum c : GenderEnum.values()) {
            if (c.getCode() == code) {
                return c.getDesc();
            }
        }
        return null;
    }

    public int getCode() {
        return code;
    }

    public String getDesc() {
        return desc;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }
}

用户对象如下:

@Data
@ToString
public class PersonVO implements Serializable {

    Long id;

    String username;

    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    Date birthday;

    Integer gender;

返回前端示例如下:

 {
 "id": "1699657986705854464",
 "username": "jack",
 "birthday": "2024-04-23 14:21:54",
 "gender": 1
 }

这时,需要将数值类型翻译为对应的描述,例如性别1应该翻译为。和上篇的数据脱敏一样,后端可以在数据库查询或者反序列化返回Http响应时进行处理。
在这里插入图片描述

2. 案例演示

演示需求:将性别编码值翻译后,返回给前端。

示例:

 {
 "id": "1699657986705854464",
 "username": "jack",
 "birthday": "2024-04-23 14:21:54",
 "gender": 1,
 "genderText":"男"
 }

2.1 修改枚举

定义一个公共的枚举接口,定义一个根据编码值获取对应描述的方法:

public interface CommonEnum {

    /**
     * 根据编码值获取描述
     */
    String getDescription(int code);
}

GenderEnum 实现公共枚举接口,并实现其方法,这里枚举类相当于一本字典,根据编码值可以翻译为描述字符串,实际开发时,也可以使用数据库或者缓存,建立专门的字典表进行维护:

public enum GenderEnum implements CommonEnum {

    MAN(1, "男"),

    WOMAN(2, "女");

    GenderEnum(int code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    private int code;

    private String desc;

    @Override
    public String getDescription(int code) {
        for (GenderEnum c : GenderEnum.values()) {
            if (c.getCode() == code) {
                return c.getDesc();
            }
        }
        return "";
    }

    public int getCode() {
        return code;
    }

    public String getDesc() {
        return desc;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }
}

2.2 定义注解

定义一个字典注解,这里使用枚举类作为字典:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@JacksonAnnotationsInside
public @interface Dict {

    /**
     * 指定后缀
     * 翻译后的属性名称:添加了注解的属性名+指定后缀
     */
    String suffix() default "Text";

    /**
     * 字典使用枚举(实际开发可以使用数据库或者缓存)
     */
    Class<? extends CommonEnum> using();
}

2.3 自定义序列化器

自定义序列化器执行翻译写出操作:

public class DictJsonSerializer extends StdSerializer<Object> {

    private CommonEnum commonEnum;

    protected DictJsonSerializer() {
        super(Object.class);
    }

    protected DictJsonSerializer( CommonEnum commonEnum) {
        super(Object.class);
        this.commonEnum = commonEnum;
    }

    /**
     * 序列化
     */
    @Override
    public void serialize(Object code, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        // 获取枚举对应的翻译值并写出
        String description =commonEnum.getDescription(Integer.parseInt(code.toString()));
        jsonGenerator.writeString(description);
    }
}

2.4 自定义装饰器

自定义Bean对象序列化装饰器,解析添加了@Dict注解的属性,据此新建一个虚拟属性:

public class DictBeanSerializerModifier extends BeanSerializerModifier {

    public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
        // 1. 创建新的属性集合
        List<BeanPropertyWriter> newBeanProperties = CollUtil.newArrayList(beanProperties);
        // 2. 循环所有属性
        for (BeanPropertyWriter propertyWriter : beanProperties) {
            // 3. 获取注解 @Dict
            Dict annotation = propertyWriter.getAnnotation(Dict.class);
            if (annotation == null) {
                annotation = propertyWriter.getContextAnnotation(Dict.class);
            }
            if (annotation != null) {
                // 4. 新建一个虚拟属性(名称为:添加了注解的属性名+指定后缀)
                NameTransformer transformer = NameTransformer.simpleTransformer("", annotation.suffix());
                BeanPropertyWriter newProperty = propertyWriter.rename(transformer);
                CommonEnum commonEnum = null;
                Class<? extends CommonEnum> using = annotation.using();
                // 5. 获取枚举示例(无法反射,所以直接 IF 判断)
                if (GenderEnum.class.isAssignableFrom(using)) {
                    commonEnum = GenderEnum.MAN;
                }
                // 6. 设置虚拟属性的序列化器
                newProperty.assignSerializer(new DictJsonSerializer(commonEnum));
                newBeanProperties.add(newProperty);
            }
        }
        return newBeanProperties;
    }
}

2.5 配置

添加Spring配置类,注册自定义的ObjectMapper,并设置BeanSerializerModifier

@Configuration
public class ObjectMapperConfig {

    @Bean
    @Primary
    ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
        ObjectMapper objectMapper = builder.createXmlMapper(false).build();
        SerializerFactory serializerFactory = objectMapper
                .getSerializerFactory()
                .withSerializerModifier(new DictBeanSerializerModifier());
        objectMapper.setSerializerFactory(serializerFactory);
        return objectMapper;
    }
}

2.6 测试

用户类添加翻译注解:

@Data
@ToString
public class PersonVO implements Serializable {

    Long id;

    String username;

    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    Date birthday;

    @Dict(using = GenderEnum.class)
    Integer gender;

访问测试接口:

    @RequestMapping("/test")
    public PersonVO test() {
        PersonVO vo = new PersonVO();
        vo.setId(1699657986705854464L);
        vo.setUsername("jack");
        vo.setBirthday(new Date());
        vo.setGender(2);
        return vo;
    }

返回结果:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1618656.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JVM垃圾收集器--分区收集器

G1收集器 G1&#xff08;Garbage-First Garbage Collector&#xff09;在 JDK 1.7 时引入&#xff0c;在 JDK 9 时取代 CMS 成为了默认的垃圾收集器。G1 有五个属性&#xff1a;分代、增量、并行、标记整理、STW。 分代 G1收集器 将内部分为多个大小相等的区域&#xff0c;另…

2024五一劳动节市集露营生活节活动策划方案

2024五一劳动节市集露营生活节&#xff08;向野而生 躺平生活节主题&#xff09;活动策划方案 方案页码&#xff1a;72页 文件格式&#xff1a;pptx 方案简介&#xff1a; 五一躺平生活节 咖啡一饮&#xff0c;书本一翻&#xff0c;轻松又自在,看着窗外的阳光&#xff0c;…

2024商业地产五一劳动节健康大会朋克养生市集活动策划方案

2024商业地产五一劳动节健康大会朋克养生市集&#xff08;带薪健康 快乐打工主题&#xff09;活动策划方案 活动策划信息&#xff1a; 方案页码&#xff1a;53页 文件格式&#xff1a;PPT 方案简介&#xff1a; 打工不养生 赚钱养医生 期待已久的五一假期&#xff0c; …

进口主食冻干高价是营销炒作还是物有所值?百利冻干真相揭秘分享

提及高端主食冻干&#xff0c;百利无疑也隶属其中。在各大平台上搜索“主食冻干”等相关词汇时&#xff0c;百利总能脱颖而出。在历次的双11、618等购物狂欢中&#xff0c;百利的销量都还不错。说明其高昂的价格也让许多宠物主人犹豫不决&#xff0c;只能等待大促时的优惠。那么…

【python】Python成语接龙游戏[1-3难度均有](源码+数据)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

好友关注-实现分页查询收邮箱

9.5好友关注-实现分页查询收邮箱 需求&#xff1a;在个人主页的“关注”卡片中&#xff0c;查询并展示推送的Blog信息&#xff1a; 具体操作如下&#xff1a; 1、每次查询完成后&#xff0c;我们要分析出查询出数据的最小时间戳&#xff0c;这个值会作为下一次查询的条件 2…

Midjourney是什么?Midjourney怎么用?怎么注册Midjourney账号?国内怎么使用Midjourney?多人合租Midjourney拼车

Midjourney是什么 OpenAI发布的ChatGPT4引领了聊天机器人的竞争浪潮&#xff0c;随后谷歌推出了自己的AI聊天机器人Bard&#xff0c;紧接着微软推出了Bing Chat&#xff0c;百度也推出了文心一言&#xff0c;这些聊天机器人的推出&#xff0c;标志着对话式AI技术已经达到了一个…

每日一题 —— 最大子数组之和(动态规划)

1.链接 53. 最大子数组和 - 力扣&#xff08;LeetCode&#xff09; 2.描述 3.思路 4.参考代码 class Solution { public:int maxSubArray(vector<int>& nums) {int n nums.size();vector<int> dp(n1,0);int ret INT_MIN;for(int i 1;i<n;i){dp[i] ma…

pytest教程-29-重复执行用例插件-pytest-repeat

领取资料&#xff0c;咨询答疑&#xff0c;请➕wei: June__Go 上一小节我们学习了设置用例超时时间插件pytest-timeout&#xff0c;本小节我们讲解一下pytest重复执行用例插件pytest-repeat。 前言 做功能测试的时候&#xff0c;经常会遇到某个模块不稳定&#xff0c;偶然会…

STM32 I²C通信

一、IC总线通信 1.1 IC总线特点 IC&#xff08;Inter Integrated Circuit&#xff0c;集成电路总线&#xff09;&#xff0c;通过串行数据线SDA&#xff08;Serial Data&#xff09;和串行时钟线SCL&#xff08;Serial Clock&#xff09;来完成数据的传输。 特点&#xff1a;…

CentOS配置JDK8环境并安装配置neo4j

1. 工具安装 1. 安装wget yum install -y wget2. 安装vim yum install -y vim-enhanced2. 配置JDK 1. 安装JDK 先到官网下载jdk8的压缩包&#xff0c;点我传送&#xff0c;并将压缩包上传到虚拟机的/usr/local目录下。 cd /usr/local # 进入 /usr/local目录 tar -zxvf jdk-…

代码随想录算法训练营第20天 |654.最大二叉树、 617.合并二叉树、700.二叉搜索树中的搜索、98.验证二叉搜索树

代码随想录算法训练营第20天 |654.最大二叉树、 617.合并二叉树、700.二叉搜索树中的搜索、98.验证二叉搜索树 自己看到题目的第一想法看完代码随想录之后的想法自己实现过程中遇到哪些困难 链接: 654.最大二叉树 链接: 617.合并二叉树 链接: 700.二叉搜索树中的搜索 链接: 98.…

【MATLAB源码-第196期】基于matlab的A*融合DWA算法栅格路径规划仿真,画出路径图、姿态角度以及线角速度。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 A算法与DWA算法的融合是一个高效的路径规划策略&#xff0c;这种策略将A算法的全局路径规划能力与DWA算法的局部避障能力结合起来&#xff0c;以期达到更快、更安全的导航效果。以下是对这种融合策略的详细描述。 一、基本概…

达梦工具使用-DTS

文章目录 前言一、图形化界面的DTS1.从Oracle迁移到DM2.从DM迁移到Oracle3.同构DM数据库迁移 二、命令行方式的DTS总结 前言 DTS是达梦数据库自带的数据迁移工具&#xff0c;主要场景适用于同构数据库轻量数据级之间数据迁移&#xff0c;当数据量不大时&#xff0c;也可用于不…

解决“找不到MSVCP120.dll”或“MSVCP120.dll丢失”的错误方法

在计算机使用过程中&#xff0c;遇到诸如“找不到MSVCP120.dll”或“MSVCP120.dll丢失”的错误提示并不罕见。这类问题往往会导致某些应用程序无法正常运行&#xff0c;给用户带来困扰。本文旨在详细阐述MSVCP120.dll文件的重要性、其丢失的可能原因&#xff0c;以及解决方法&a…

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之五 简单进行车牌检测和识别

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之五 简单进行车牌检测和识别 目录 Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之五 简单进行车牌检测和识别 一、简单介绍 二、简单进行车牌检测和识别实现原理 …

ACRN Intel推出的虚拟机是啥样的?

前言 ACRN作为Intel为工控领域推出的一个小型化的虚拟机&#xff0c;它的特点主要有这么几个&#xff1a; 1.针对Intel的芯片做了非常强的优化 2.RT-VM实时虚拟机的实时性很好 3.CACHE缓存技术发挥的好 4.TCC技术 / 当然不是所有intel的芯片都支持&#xff0c;&#xff0c…

OKCC搭建配置什么样的服务器合适

OKCC呼叫中心系统是一种采用软硬件结合的架构方式、及分布式的IP技术&#xff0c;从多角度为企业提供整合的一体化解决方案。因此&#xff0c;搭建OKCC呼叫中心系统所使用的服务器应该满足以下几点要求&#xff1a; 稳定性&#xff1a;服务器需要具有较高的稳定性和可靠性&…

应用部署tomcat的三种方式

由于一直在用springboot框架&#xff0c;集成了tomcat&#xff0c;快忘记如何单独部署tomcat了&#xff0c;以下&#xff0c;记录一下&#xff1a; 部署tomcat有三种方式&#xff1a; 一、方式一&#xff1a;将war包丢进webapps 这是最简单粗暴的方式&#xff1a;将web工程打…

平均月薪超4.6万!AI领域重磅课程汇总,哈佛,斯坦福,微软,谷歌等出品!

2023年底&#xff0c;由脉脉高聘人才智库发布的《2023泛人工智能人才洞察》报告显示&#xff0c;2023年前八个月内新发布的AI岗位平均月薪超过了4.6万元&#xff0c;而且人才供不应求&#xff0c;甚至出现了5个岗位争夺2个人才的情况。 本文章整理了10项来自全球各高校与知名企…