当前位置:首页 > 编程笔记 > 正文
已解决

springboot对象序列化自定义序列化注解

来自网友在路上 175875提问 提问时间:2023-09-25 04:39:11阅读次数: 75

最佳答案 问答题库758位专家为你答疑解惑

概述

在开发中有时候会遇到一些内容返回时需要翻译,或者一些内容在序列化之前需要特殊处理(脱敏啥的)。

一般对单个属性可以直接用jackson的序列化注解对某个属性单独处理
com.fasterxml.jackson.databind.annotation.JsonSerialize(using= xxx.class)

但是直接使用不太灵活,可以进一步引入注解,配上参数来灵活的序列化。

这里就会涉及到
com.fasterxml.jackson.databind.ser.ContextualSerializer
它可以通过回调拿到序列化的属性上的注解参数。

我的jdk版本是17
springboot3.1.2
因为用了spring-web,默认用的就是jackson,所以不需要再额外引入jackson依赖了

上demo

package org.xxx.common.translation.annotation;import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.qps.common.translation.core.handler.TranslationHandler;import java.lang.annotation.*;/*** 通用翻译注解*/
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
@Documented
//让jackson的注解拦截器(com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector)能发现当前注解
@JacksonAnnotationsInside
//指定当前注解修饰的属性/方法使用具体哪个序列化类来序列化
@JsonSerialize(using = TranslationHandler.class)
public @interface Translation {/*** 类型 (需与实现类上的 {@link TranslationType} 注解type对应)* <p>* 默认取当前字段的值 如果设置了 @{@link Translation#mapper()} 则取映射字段的值*/String type();/*** 映射字段 (如果不为空则取此字段的值)*/String mapper() default "";/*** 其他条件 例如: 字典type(sys_user_sex)*/String other() default "";}package org.xxx.xxx.translation.core.handler;import cn.hutool.core.util.ObjectUtil;
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.xxx.common.core.utils.StringUtils;
import org.xxx.common.core.utils.reflect.ReflectUtils;
import org.xxx.common.translation.annotation.Translation;
import org.xxx.common.translation.core.TranslationInterface;
import lombok.extern.slf4j.Slf4j;import java.io.IOException;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;/*** 翻译处理器* 通过回调(ContextualSerializer.createContextual),将声明的属性上的Translation注解,传递给当前的序列化器*/
@Slf4j
public class TranslationHandler extends JsonSerializer<Object> implements ContextualSerializer {/*** 全局翻译实现类映射器*/public static final Map<String, TranslationInterface<?>> TRANSLATION_MAPPER = new ConcurrentHashMap<>();private Translation translation;@Overridepublic void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {//这里是通过一个接口,提前定义好了一批翻译类,这里通过注解上的type去获取对应的翻译类TranslationInterface<?> trans = TRANSLATION_MAPPER.get(translation.type());if (ObjectUtil.isNotNull(trans)) {// 如果映射字段不为空 则取映射字段的值if (StringUtils.isNotBlank(translation.mapper())) {//通过反射去调用注解中指定的属性(比如shopName通过shopId去翻译)value = ReflectUtils.invokeGetter(gen.getCurrentValue(), translation.mapper());}// 如果为 null 直接写出if (ObjectUtil.isNull(value)) {gen.writeNull();return;}//调用翻译类进行翻译Object result = trans.translation(value, translation.other());gen.writeObject(result);} else {gen.writeObject(value);}}//通过回调,在第一次调用的时候获取注解参数,并赋值给当前class中的注解变量@Overridepublic JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {Translation translation = property.getAnnotation(Translation.class);if (Objects.nonNull(translation)) {this.translation = translation;return this;}return prov.findValueSerializer(property.getType(), property);}
}
查看全文

99%的人还看了

猜你感兴趣

版权申明

本文"springboot对象序列化自定义序列化注解":http://eshow365.cn/6-13235-0.html 内容来自互联网,请自行判断内容的正确性。如有侵权请联系我们,立即删除!