解决使用Redis 配置替换fastjson 反序列化报错 com.alibaba.fastjson.JSONException: autoType is not support

本文详细介绍了在使用FastJSON进行反序列化时遇到的autoTypeisnotsupport错误原因及解决方案。通过在GenericFastJson2JsonRedisSerializer中添加特定包名至ParserConfig的白名单,成功解决了这一问题。

这几天用tomcat、nginx、redis配置socket的负载均衡在做信息共享的使用fastjson反序列化遇到了个啃爹的事情

com.alibaba.fastjson.JSONException: autoType is not support

网上查了下这个错误的原因,发现有很多人也遇到了。

原来是fastjson默认是开启的了autoType

只要在我们新建的GenericFastJson2JsonRedisSerializer里面添加白名单既可

贴上GenericFastJson2JsonRedisSerializer代码

/**
 * Created by DESTINY on 2018/11/7.
 */
public class GenericFastJson2JsonRedisSerializer<T> implements RedisSerializer<T> {

    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

    static {
        ParserConfig.getGlobalInstance().addAccept("com.xxx.xxx.bo");
        ParserConfig.getGlobalInstance().addAccept("com.xxx.xxx.redis");
    }

    public GenericFastJson2JsonRedisSerializer() {
        super();
    }

    @Override
    public byte[] serialize(T t) throws SerializationException {
        if (t == null) {
            return new byte[0];
        }
        FastJsonWraper<T> wraperSet = new FastJsonWraper<>(t);
        return JSON.toJSONString(wraperSet, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
    }

    @Override
    public T deserialize(byte[] bytes) throws SerializationException {
        if (bytes == null || bytes.length <= 0) {
            return null;
        }
        String deserializeStr = new String(bytes, DEFAULT_CHARSET);
        FastJsonWraper<T> wraperGet = JSON.parseObject(deserializeStr, FastJsonWraper.class);
        return wraperGet.getValue();
    }
}

添加:

static {
        ParserConfig.getGlobalInstance().addAccept("com.xxx.xxx.bo");
        ParserConfig.getGlobalInstance().addAccept("com.xxx.xxx.redis");
    }

所需要添加的包名可以在redis里面获取的字符串里面打印一下

把@type的value值添加到ParserConfig的白名单里面即可

 

有错误的欢迎指正 哦!!!!看到会马上恢复

每天记录一点点。。。。即便自己是菜鸟

### 解决 Fastjson2 序列化类型转换错误 当遇到 `com.alibaba.fastjson2.JSONObject` 无法被强制转换成自定义对象(如 `com.wichatbackapi.domain.LoginUser`)的情况时,通常是因为反序列化过程中丢失了具体的类型信息。为了修复这个问题,可以采取以下几种方法: #### 方法一:调整 Redis 配置中的序列化方式 如果应用程序使用的是 Spring Boot 和 Redis 的组合,则可以通过配置 RedisTemplate 来指定更合适的序列化器来处理复杂的数据结构。 ```java @Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(factory); Jackson2JsonRedisSerializer<Object> jacksonSer = new Jackson2JsonRedisSerializer<>(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jacksonSer.setObjectMapper(om); template.setValueSerializer(jacksonSer); // 设置value的序列化规则 template.setKeySerializer(new StringRedisSerializer()); // key采用String的序列化方式 return template; } } ``` 这种方法通过引入 Jackson 进行序列化/反序列化操作,并开启默认类型的支持,从而解决Fastjson 可能带来的兼容性问题[^1]。 #### 方法二:启用 AutoType 功能并设置白名单 对于继续沿用 Fastjson2 的场景下,确保启用了其特有的 AutoType 特性和设置了合理的类名前缀列表是非常重要的。这允许在 JSON 字符串里嵌入完整的 Java 类型信息以便于后续解析。 ```properties # application.properties 或者 yml 文件中加入如下配置fastjson.parser.autoTypeSupport=true fastjson.serializer.features=WriteClassName ``` 同时,在项目的常量文件 Constants 中维护好受信任的对象前缀数组,例如: ```java // Constants.java public static final String[] JSON_WHITELIST_STR = {"org.springframework", "com.ruoyi"}; ``` 注意这里的包路径应当覆盖到实际使用的业务逻辑层实体类所在的命名空间,比如上述例子中的 `com.wichatbackapi.domain.LoginUser` 所属的位置也应包含进来[^2]。 #### 方法三:手动控制序列化过程 作为最后的选择,可以在保存数据之前先将其显式地转化为目标类型实例再存入缓存;读取时同样遵循这一原则——即总是创建一个新的 LoginUser 对象并将来自 Redis 的原始 Map 数据填充进去。 ```java // 存储至Redis前的操作 LoginUser loginUser = ...; // 获取登录用户的实例 redisTemplate.opsForValue().set(key, objectMapper.writeValueAsString(loginUser)); // 从Redis取出后的操作 String jsonStr = (String) redisTemplate.opsForValue().get(key); loginUser = objectMapper.readValue(jsonStr, LoginUser.class); ``` 这种方式虽然绕过了直接依赖第三方库特性所带来的风险,但也增加了编码工作量以及潜在的手动映射失误的可能性。
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值