Jackson进行序列化和反序列化解决

  • 当后端响应给前端的数据中包含了id或者特殊标识(可自定义)的时候,把当前数据进行转换为String类型
  • 当前端传递后后端的dto中有id或者特殊标识(可自定义)的时候,把当前数据转为Integer或Long类型。

特殊标识类说明:

下面是一些工具类

IdEncrypt 自定义注解 作用在需要转换类型的字段属性上,用于非id的属性上

java 复制代码
import com.fasterxml.jackson.annotation.JacksonAnnotation;
​
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
​
@JacksonAnnotation
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
public @interface IdEncrypt {
}

这段代码定义了一个自定义的Java注解 IdEncrypt。它使用了 @JacksonAnnotation 注解,表示它与Jackson库兼容,可以用于JSON处理。@Retention(RetentionPolicy.RUNTIME) 注解指定了这个注解在运行时应该保留,允许通过反射进行检查。此外,@Target 注解指明了这个注解可以应用于字段(ElementType.FIELD)、方法(ElementType.METHOD)和参数(ElementType.PARAMETER)。然而,这个注解本身并没有包含任何元素或属性。

序列化和反序列化类说明:

  • ConfusionSerializer 用于序列化自增数字的混淆

    scala 复制代码
    public class ConfusionSerializer extends JsonSerializer<Object> {
    ​
        @Override
        public  void serialize(Object value, JsonGenerator jsonGenerator, SerializerProvider serializers) throws IOException {
            try {
                if (value != null) {
                    jsonGenerator.writeString(value.toString());
                    return;
                }
            }catch (Exception e){
                e.printStackTrace();
            }
            serializers.defaultSerializeValue(value, jsonGenerator);
        }
    }

这段代码定义了一个名为 ConfusionSerializer 的Java类,它扩展了 JsonSerializer<Object> 类。该类的作用是自定义JSON序列化过程。

serialize 方法中,首先检查传入的 value 是否为非空。如果不为空,将其转换为字符串并通过 jsonGenerator 写入JSON。如果转换过程中发生异常,会打印异常信息。如果 value 为空或转换异常,则使用 Serializers.defaultSerializeValue 方法进行默认的JSON序列化操作。

这个类的目的是在序列化对象为JSON时,提供了自定义的逻辑,允许对特定类型的对象进行特殊处理,而不是使用默认的序列化规则。

  • ConfusionDeserializer 用于反序列化自增数字的混淆解密

    scala 复制代码
    public class ConfusionDeserializer extends JsonDeserializer<Object> {
    ​
        JsonDeserializer<Object>  deserializer = null;
        JavaType type =null;
    ​
        public  ConfusionDeserializer(JsonDeserializer<Object> deserializer, JavaType type){
            this.deserializer = deserializer;
            this.type = type;
        }
    ​
        @Override
        public  Object deserialize(JsonParser p, DeserializationContext ctxt)
                throws IOException{
            try {
                if(type!=null){
                    if(type.getTypeName().contains("Long")){
                        return Long.valueOf(p.getValueAsString());
                    }
                    if(type.getTypeName().contains("Integer")){
                        return Integer.valueOf(p.getValueAsString());
                    }
                }
                return IdsUtils.decryptLong(p.getValueAsString());
            }catch (Exception e){
                if(deserializer!=null){
                    return deserializer.deserialize(p,ctxt);
                }else {
                    return p.getCurrentValue();
                }
            }
        }
    }

这段代码定义了一个名为 ConfusionDeserializer 的Java类,它用于反序列化带有混淆加密的自增数字。以下是代码的主要作用和解释:

  1. 构造函数:

    • ConfusionDeserializer 类有一个构造函数,接受两个参数:JsonDeserializer<Object> 类型的 deserializerJavaType 类型的 type。这些参数用于初始化类中的成员变量。
  2. 反序列化逻辑:

    • deserialize 方法是该类的主要方法,用于实现反序列化逻辑。
    • 方法首先检查 type 是否为 LongInteger 类型。如果是,它将从JSON解析器 (JsonParser p) 中获取值并转换为相应的 LongInteger 对象。
    • 如果 type 不是基本数据类型,它将调用 IdsUtils.decryptLong(p.getValueAsString()) 方法,该方法用于将混淆加密的字符串解密为原始的长整型数字。
    • 如果在解密过程中发生异常,代码会捕获异常并检查是否有传入的 deserializer。如果有,它将使用传入的 deserializer 进行反序列化。如果没有传入的 deserializer,它将返回当前JSON解析器的当前值。

总的来说,ConfusionDeserializer 类用于根据输入的 type 和混淆加密的字符串值,将其反序列化为对应的原始数字对象(LongInteger),或者使用传入的 deserializer 进行反序列化处理。这个类的设计允许在特定场景下,根据需要选择不同的反序列化策略。

  • ConfusionSerializerModifier 用于过滤序列化时处理的字段

    scala 复制代码
    public class ConfusionSerializerModifier extends BeanSerializerModifier {
    ​
        @Override
        public List<BeanPropertyWriter> changeProperties(SerializationConfig config,
                                                         BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
            List<BeanPropertyWriter> newWriter = new ArrayList<>();
            for(BeanPropertyWriter writer : beanProperties){
                String name = writer.getType().getTypeName();
                if(null == writer.getAnnotation(IdEncrypt.class) && !writer.getName().equalsIgnoreCase("id")){
                    newWriter.add(writer);
                } else {
                    writer.assignSerializer(new ConfusionSerializer());
                    newWriter.add(writer);
                }
            }
            return newWriter;
        }
    }

这段代码定义了一个名为 ConfusionSerializerModifier 的Java类,它继承自 BeanSerializerModifier。该类的主要作用是在序列化过程中过滤处理字段,根据字段上的注解和字段名进行不同的处理。

具体作用解释如下:

  1. changeProperties 方法:

    • ConfusionSerializerModifier 类重写了 BeanSerializerModifier 中的 changeProperties 方法。
    • 这个方法在序列化时被调用,接收三个参数:SerializationConfig(序列化配置信息)、BeanDescription(Java Bean 的描述信息)和 beanProperties(需要序列化的Bean属性列表)。
    • 在这个方法中,代码遍历传入的 beanProperties 列表,逐个处理每个属性。
  2. 字段过滤逻辑:

    • 对于每个属性(BeanPropertyWriter),首先检查该属性上是否有 IdEncrypt 注解(自定义注解)。如果没有这个注解并且字段名不是 "id",则保留该属性,不做特殊处理,将其添加到 newWriter 列表中。
    • 如果属性上有 IdEncrypt 注解或者字段名是 "id",则将该属性的序列化处理器(Serializer)设置为 ConfusionSerializer 类的实例,然后将该属性添加到 newWriter 列表中。
    • 最终,返回经过处理的属性列表 newWriter

总的来说,ConfusionSerializerModifier 类的作用是根据字段上的注解和字段名,在序列化过程中选择性地使用 ConfusionSerializer 对象进行处理。这种设计允许在序列化时,针对特定的字段进行自定义的序列化操作,以满足特定的需求或安全要求。

  • ConfusionDeserializerModifier 用于过滤反序列化时处理的字段

    scala 复制代码
    public class ConfusionDeserializerModifier extends BeanDeserializerModifier {
    ​
        @Override
        public BeanDeserializerBuilder updateBuilder(final DeserializationConfig config, final BeanDescription beanDescription, final BeanDeserializerBuilder builder) {
            Iterator it = builder.getProperties();
    ​
            while (it.hasNext()) {
                SettableBeanProperty p = (SettableBeanProperty) it.next();
                if ((null != p.getAnnotation(IdEncrypt.class)||p.getName().equalsIgnoreCase("id"))) {
                    JsonDeserializer<Object> current = p.getValueDeserializer();
                    builder.addOrReplaceProperty(p.withValueDeserializer(new ConfusionDeserializer(p.getValueDeserializer(),p.getType())), true);
                }
            }
            return builder;
        }
    }

这段代码定义了一个名为 ConfusionDeserializerModifier 的Java类,它继承自 BeanDeserializerModifier。该类的主要作用是在反序列化过程中过滤处理字段,根据字段上的注解和字段名进行不同的处理。

具体作用解释如下:

  1. updateBuilder 方法:

    • ConfusionDeserializerModifier 类重写了 BeanDeserializerModifier 中的 updateBuilder 方法。
    • 这个方法在反序列化时被调用,接收三个参数:DeserializationConfig(反序列化配置信息)、BeanDescription(Java Bean 的描述信息)和 builder(用于构建Bean的反序列化器的构建器)。
  2. 字段过滤逻辑:

    • 在方法内部,代码获取了 builder 中的属性迭代器(Iterator),然后遍历所有属性。
    • 对于每个属性(SettableBeanProperty),首先检查该属性上是否有 IdEncrypt 注解(自定义注解)或者字段名是否为 "id"。
    • 如果属性上有 IdEncrypt 注解或者字段名是 "id",则获取当前属性的反序列化器(JsonDeserializer<Object>)。
    • 接着,通过构建器的 addOrReplaceProperty 方法,将当前属性的反序列化器替换为 ConfusionDeserializer 类的实例,并将新的属性添加到构建器中。这样,对于被标记或命名为 "id" 的属性,将使用 ConfusionDeserializer 进行自定义的反序列化操作。

总的来说,ConfusionDeserializerModifier 类的作用是根据字段上的注解和字段名,在反序列化过程中选择性地使用 ConfusionDeserializer 对象进行处理。这种设计允许在反序列化时,根据特定的字段,实现自定义的反序列化逻辑,以满足特定的需求或安全要求。

  • ConfusionModule 用于注册模块和修改器

    typescript 复制代码
    public class ConfusionModule extends Module {
    ​
        public final static String MODULE_NAME = "jackson-confusion-encryption";
        public final static Version VERSION = new Version(1,0,0,null,"heima",MODULE_NAME);
    ​
        @Override
        public String getModuleName() {
            return MODULE_NAME;
        }
    ​
        @Override
        public Version version() {
            return VERSION;
        }
    ​
        @Override
        public void setupModule(SetupContext context) {
            context.addBeanSerializerModifier(new ConfusionSerializerModifier());
            context.addBeanDeserializerModifier(new ConfusionDeserializerModifier());
        }
    ​
        /**
         * 注册当前模块
         * @return
         */
        public static ObjectMapper registerModule(ObjectMapper objectMapper){
            //CamelCase策略,Java对象属性:personId,序列化后属性:persionId
            //PascalCase策略,Java对象属性:personId,序列化后属性:PersonId
            //SnakeCase策略,Java对象属性:personId,序列化后属性:person_id
            //KebabCase策略,Java对象属性:personId,序列化后属性:person-id
            // 忽略多余字段,抛错
            objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    //        objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
            return objectMapper.registerModule(new ConfusionModule());
        }
    ​
    }

    这段代码定义了一个名为 ConfusionModule 的类,它是一个 Jackson 模块(Module)。这个模块主要用于注册自定义的序列化和反序列化修改器(Modifier),以及设置一些默认的 Jackson 配置。以下是这段代码的主要作用和解释:

  1. 模块信息和版本定义:

    • 定义了模块的名称 MODULE_NAME 和版本 VERSION。这些信息用于标识和区分不同的 Jackson 模块。
  2. getModuleNameversion 方法:

    • 实现了 Module 抽象类中的方法,分别返回模块的名称和版本信息。
  3. setupModule 方法:

    • 实现了 Module 抽象类中的方法,用于设置模块。
    • 在这个方法中,通过 context.addBeanSerializerModifiercontext.addBeanDeserializerModifier 分别注册了自定义的序列化修改器 ConfusionSerializerModifier 和反序列化修改器 ConfusionDeserializerModifier。这些修改器将在序列化和反序列化过程中对特定字段进行自定义处理。
  4. registerModule 静态方法:

    • 这个方法用于注册当前模块到一个 ObjectMapper 对象中,以便在使用 Jackson 进行序列化和反序列化时应用该模块。
    • 在方法内部,设置了一些 Jackson 的配置,如禁用对未知属性的抛错(FAIL_ON_UNKNOWN_PROPERTIES),以及可能的属性命名策略。
    • 最后,通过 objectMapper.registerModule(new ConfusionModule()) 注册了当前的 ConfusionModule 模块到传入的 ObjectMapper 对象中。

总的来说,ConfusionModule 类的作用是为 Jackson 提供了一个自定义模块,该模块包含了序列化和反序列化的修改器,并可以通过 registerModule 方法轻松地将这个模块添加到 ObjectMapper 中,以实现对特定字段的自定义处理和一些默认的配置。

  • InitJacksonConfig 提供自动化配置默认ObjectMapper,让整个框架自动处理id混淆

    java 复制代码
    @Configuration
    public class InitJacksonConfig {
    ​
        @Bean
        public ObjectMapper objectMapper() {
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper = ConfusionModule.registerModule(objectMapper);
            return objectMapper;
        }
    ​
    }

这段代码是一个配置类,用于初始化 Jackson 库的 ObjectMapper 对象,并注册一个自定义的 ConfusionModule 模块。

ObjectMapper 是 Jackson 库的核心组件之一,负责序列化和反序列化 Java 对象与 JSON 数据之间的转换。通过配置 ObjectMapper,我们可以自定义与控制对象的序列化和反序列化行为。

在该配置类中,通过定义一个名为 objectMapperBean 方法来创建和配置 ObjectMapper 对象。首先,创建一个新的 ObjectMapper 实例,并通过 ConfusionModuleregisterModule 方法将自定义的混淆模块注册到 ObjectMapper 中。ConfusionModule 可以处理对象的 id 混淆,具体的实现逻辑在 ConfusionModule 类中定义。

配置完成后,这个 ObjectMapper 对象可以被其他组件或类注入和使用,用于处理对象的序列化和反序列化。

相关推荐
向前看-4 分钟前
验证码机制
前端·后端
xlsw_6 分钟前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
神仙别闹1 小时前
基于java的改良版超级玛丽小游戏
java
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭1 小时前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
暮湫2 小时前
泛型(2)
java
超爱吃士力架2 小时前
邀请逻辑
java·linux·后端
南宫生2 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
转码的小石2 小时前
12/21java基础
java
李小白662 小时前
Spring MVC(上)
java·spring·mvc
GoodStudyAndDayDayUp2 小时前
IDEA能够从mapper跳转到xml的插件
xml·java·intellij-idea