Gson反序列化 子类、接口实现类

当使用json反序列化如SpringSecurity的GrantedAuthority接口时,由于无法确定具体实现类,导致反序列化失败。文章提出了解决方案,即保存对象原始类型并在反序列化时装配对应的实现类。通过创建自定义的JsonDeserializer和注册类型适配器,能够处理父类或接口类型的反序列化问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

起源于SpringSecurity的权限GrantedAuthority无法反序列化,fastjson反序列化出来的结果直接为空,使用gson报错为:

Interfaces can't be instantiated! Register an InstanceCreator or a TypeAdapter for this type.

原因:json反序列化的接收对象为一个父对象/接口类型时,无法确定实际类型。模型如下

新建一个接口/父类
在这里插入图片描述
随便写两个实现类
在这里插入图片描述
在这里插入图片描述
需要序列化反序列化的类
在这里插入图片描述
测试,因为实际类型无法确认,则无法反序列化在这里插入图片描述
解决思路:需要保存对象的原始类型,反序列化时装配实现类对象
我此处新增了一个变量用来保存类名,实际使用其他编号id也可代替
在这里插入图片描述
在这里插入图片描述
自定义一个反序列化配置,用来识别父类下的各个子类,反序列化时装配其原始类型

public class FatherDeserializer implements JsonDeserializer<Father> {

    private Gson gson = new Gson();

    private Map<String, Class<? extends Father>> sonsType = new HashMap<>(16);

    public FatherDeserializer() {
        sonsType.put("Son1", Son1.class);
        sonsType.put("Son2", Son2.class);
    }

    @Override
    public Father deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        JsonObject jsonObject = json.getAsJsonObject();
        Class<? extends Father> clazz = this.sonsType.get(jsonObject.get("className").getAsString());
        return gson.fromJson(json, clazz);
    }
}

构建Gson对象时传入自定义的反序列化配置,Father类型使用自定义的FatherDeserializer

        Gson gson = new GsonBuilder()
                .serializeNulls()
                .registerTypeAdapter(Father.class, new FatherDeserializer())
                .create();

测试使用在这里插入图片描述

<think>好的,我现在需要处理用户关于Spring框架中反序列化用法及常见问题的查询。首先,我需要回忆Spring中处理反序列化的相关知识,尤其是涉及到的注解、配置以及常见问题。 用户提到他们想了解反序列化的用法和常见问题,所以应该从这两个方面展开。首先,用法方面,Spring常用的工具有Jackson和Gson,可能涉及注解如@JsonFormat、@JsonIgnore,以及配置自定义序列化器。需要结合引用中的内容,比如引用[2]提到的time字段的序列化格式问题,可以通过注解解决。引用[3]提到静态属性不会被序列化,这也需要提及。 接下来是常见问题,比如日期格式问题(如引用[2]中的例子)、静态字段问题(引用[3])、循环引用、多态类型处理等。另外,用户提供的引用[4]提到了Spring1链的反序列化漏洞,这可能涉及到安全方面的问题,比如远程代码执行,需要提醒注意安全配置。 还要注意引用[1]中提到序列化算法的重要性,Spring默认使用Jackson,可能涉及性能问题,或者跨语言支持,但Jackson本身是支持JSON的,跨语言较好。可能需要对比其他序列化方式。 现在需要组织内容,确保结构清晰。先介绍用法,包括常用注解、配置方法、自定义序列化器。然后讲常见问题,每个问题给出原因和解决方案。最后提到安全方面的注意事项,比如反序列化漏洞的防范。 需要检查引用是否正确应用,比如日期格式对应引用[2],静态字段对应引用[3],序列化算法引用[1],安全方面引用[4]。确保每个引用自然融入内容,并在段落末尾正确标注。 可能还需要生成相关问题,考虑用户可能进一步的问题,比如如何自定义序列化、处理循环引用、安全最佳实践等。 最后,确保回答符合系统级指令,数学公式用$...$,独立公式用$$...$$,但这个问题可能不涉及数学公式。使用中文,结构清晰,分点说明,代码示例正确,比如展示使用@JsonFormat的代码。</think>### Spring框架中的反序列化用法及常见问题 #### 一、反序列化用法 1. **注解驱动配置** Spring通过Jackson库(默认)或Gson库实现JSON反序列化,常用注解包括: - `@RequestBody`:将HTTP请求体反序列化Java对象。 - `@JsonFormat`:自定义日期格式,例如修正时间字段格式问题[^2]: ```java public class Example { @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date time; } ``` - `@JsonIgnore`:忽略字段的反序列化。 2. **配置自定义反序列化器** 通过继承`JsonDeserializer`实现自定义逻辑,例如处理特殊字符串到枚举的转换: ```java public class CustomDeserializer extends JsonDeserializer<MyEnum> { @Override public MyEnum deserialize(JsonParser p, DeserializationContext ctxt) { // 自定义解析逻辑 } } ``` 3. **多态类型处理** 使用`@JsonTypeInfo`支持多态类型反序列化: ```java @JsonTypeInfo(use = Id.NAME, property = "type") @JsonSubTypes({@Type(value = SubClassA.class, name = "A")}) public abstract class BaseClass {} ``` --- #### 二、常见问题及解决方案 1. **日期格式不一致** - **现象**:默认日期格式如`2024-11-28T11:11:11`不符合需求[^2]。 - **解决**:使用`@JsonFormat`显式指定格式。 2. **静态字段被忽略** - **现象**:静态属性(如`static String`)未被序列化/反序列化[^3]。 - **原因**:静态字段属于类级别,不参与对象实例的序列化。 - **建议**:避免依赖静态字段存储需持久化的数据。 3. **循环引用导致栈溢出** - **现象**:对象A引用对象B,B又引用A,导致JSON序列化失败。 - **解决**:使用`@JsonManagedReference`和`@JsonBackReference`注解标记双向关系。 4. **多态类型反序列化失败** - **现象**:无法根据JSON数据确定具体子类类型。 - **解决**:通过`@JsonTypeInfo`指定类型标识字段。 5. **安全漏洞(反序列化攻击)** - **风险**:攻击者构造恶意数据触发远程代码执行(如Spring1链利用动态代理漏洞)[^4]。 - **防范**:限制反序列化的类范围,使用白名单校验。 --- #### 三、安全实践建议 - **禁用危险类型的反序列化**:配置Jackson的`PolymorphicTypeValidator`限制允许的类。 - **日志监控**:记录反序列化异常,及时发现攻击尝试。 - **依赖更新**:定期升级Spring和Jackson版本,修复已知漏洞[^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值