[alibaba/fastjson]fastjson 无法反序列会redis存储的内容

2025-10-31 942 views
0

配置:

@Bean
public LettuceConnectionFactory lettuceConnectionFactory() {
    LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder()
            .commandTimeout(Duration.ofSeconds(2))
            .shutdownTimeout(Duration.ZERO)
            .build();
    RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration(host, port);
    configuration.setPassword(RedisPassword.of(password));
    configuration.setDatabase(database);
    return new LettuceConnectionFactory(configuration, clientConfig);
}

GenericFastJsonRedisSerializer redisSerializer = new GenericFastJsonRedisSerializer();

@Bean
public RedisTemplate<String, Serializable> redisTemplate() {
    RedisTemplate<String, Serializable> template = new RedisTemplate<>();
    template.setKeySerializer(new StringRedisSerializer());
    template.setConnectionFactory(lettuceConnectionFactory());
    template.setHashValueSerializer(redisSerializer);
    return template;
}

@Bean
public CacheManager cacheManager() {
    Duration duration = Duration.of(TIME_OUT, ChronoUnit.SECONDS);
    RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(lettuceConnectionFactory());
    RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer);
    RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig().entryTtl(duration).serializeValuesWith(pair);
    RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, defaultCacheConfig);
    return cacheManager;
}

@Bean("keyGenerator")
public KeyGenerator keyGenerator() {
    return (target, method, params) -> {
        StringBuilder sb = new StringBuilder();
        sb.append(target.getClass().getName());
        sb.append(method.getName());
        for (Object obj : params) {
            sb.append(obj.toString());
        }
        return sb.toString();
    };
}

@JsonInclude(Include.NON_NULL) public class BaseResult implements Serializable { private static final long serialVersionUID = -7642090011121424793L; private static final String SUCCESS_CODE = "1000"; private static final String SUCCESS_MSG = "success"; private String msg; private String code; private T data; }

缓存

@Cacheable(value = "findTagsList")
@Override
public BaseResult<List<String>> findTagsList(Long systemId, Long componentId) {

}

redis 内有存有如下数据 {"@type":"com.aimsphm.common.BaseResult","code":"1000","data":["按手动控制按钮","不停机","不转动","传动轴振动大","第一推进器"....],"msg":"success"}

获取redis数据的时候发现 DefaultJSONParser parser 是空的 导致每次反序列化出来的数据都是空的

基于spring boot 2.1.0.RELEASE fastjson 版本 1.2.51

回答

1

{ "@type": "com.aimsphm.common.BaseResult", "code": "1000", "data": [ "按手动控制按钮", "不停机", "不转动", "传动轴振动大", "第一推进器", "电机不运行", ... ], "msg": "success" }

findTagsList::SimpleKey [3,0]

4

@masterchengsheng 写了个测试用例 并没有出现问题啊 see https://github.com/alibaba/fastjson/blob/1c6df2ff6fc9ac320bf8c58519aa58345000d364/src/test/java/com/alibaba/json/bvt/support/spring/GenericFastJsonRedisSerializerTest.java#L61

8

@VictorZeng 我其他的没问题 就这个有问题 我跟到 GenericFastJsonRedisSerializer 反序列化这边

public Object deserialize(byte[] bytes) throws SerializationException { if (bytes != null && bytes.length != 0) { try { return JSON.parseObject(new String(bytes, IOUtils.UTF8), Object.class, defaultRedisConfig, new Feature[0]); } catch (Exception var3) { throw new SerializationException("Could not deserialize: " + var3.getMessage(), var3); } } else { return null; } }

public static T parseObject(String input, Type clazz, ParserConfig config, Feature... features) { return parseObject(input, clazz, config, (ParseProcess)null, DEFAULT_PARSER_FEATURE, features); }

可以看到 input 就是上面我发的 那串json Type 为 java.lang.Object.class

@SuppressWarnings("unchecked") public static T parseObject(String input, Type clazz, ParserConfig config, ParseProcess processor, int featureValues, Feature... features) { if (input == null) { return null; }

    if (features != null) {
        for (Feature feature : features) {
            featureValues |= feature.mask;
        }
    }

    DefaultJSONParser parser = new DefaultJSONParser(input, config, featureValues);

    if (processor != null) {
        if (processor instanceof ExtraTypeProvider) {
            parser.getExtraTypeProviders().add((ExtraTypeProvider) processor);
        }

        if (processor instanceof ExtraProcessor) {
            parser.getExtraProcessors().add((ExtraProcessor) processor);
        }

        if (processor instanceof FieldTypeResolver) {
            parser.setFieldTypeResolver((FieldTypeResolver) processor);
        }
    }

    T value = (T) parser.parseObject(clazz, null);

    parser.handleResovleTask(value);

    parser.close();

    return (T) value;
}

执行到这边 发现parser为null return 出来的value 就是 BaseResult{msg:null,code:null,data:null}

2

@masterchengsheng 能否把出问题的完整JSON提供一下 我再测试一下

7

完整的JSON

{

"@type": "com.aimsphm.common.BaseResult",

"code": "1000",

"data": [

"按手动控制按钮",

"不停机",

"不转动",

"传动轴振动大",

"第一推进器",

"电机不运行",

"电机声音异常",

"电机异响",

"防护板磨损",

"后墙板漏油",

"挤烟",

"搅拌电机",

"旷量",

"乱烟",

"门易打开",

"拍烟板不动作",

"排空手柄断",

"驱动器报警",

"失效",

"推杆轴漏油",

"无动作",

"下方漏油",

"下烟不畅",

"下烟道缺支",

"下烟器",

"显示频繁",

"箱处异声",

"烟库",

"烟库检测失效",

"烟库缺烟",

"烟库缺烟支",

"烟库少烟",

"烟库少烟信号",

"烟库探测器失效",

"烟库下烟器",

"烟库下烟通道",

"烟支存在检测器",

"烟支挤紧器",

"烟支搅动辊",

"烟支缺少或阻塞",

"烟支推烟排推烟时",

"烟支烟库缺支",

"有异声",

"右侧油箱盖漏油",

"轴漏油"

],

"msg": "success" }

是不是我redis 配置这块有问题

@Configuration @EnableCaching public class RedisConfig implements BeanClassLoaderAware {

private static final long TIME_OUT = 600;

@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.password}")
private String password;
@Value("${spring.redis.database}")
private int database;

private ClassLoader classLoader;

@Bean
public LettuceConnectionFactory lettuceConnectionFactory() {
    LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder()
            .commandTimeout(Duration.ofSeconds(2))
            .shutdownTimeout(Duration.ZERO)
            .build();
    RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration(host, port);
    configuration.setPassword(RedisPassword.of(password));
    configuration.setDatabase(database);
    return new LettuceConnectionFactory(configuration, clientConfig);
}

GenericFastJsonRedisSerializer redisSerializer = new GenericFastJsonRedisSerializer();

@Bean
public RedisTemplate<String, Serializable> redisTemplate() {
    RedisTemplate<String, Serializable> template = new RedisTemplate<>();
    template.setKeySerializer(new StringRedisSerializer());
    template.setValueSerializer(redisSerializer);
    template.setConnectionFactory(lettuceConnectionFactory());
    template.setHashValueSerializer(redisSerializer);
    return template;
}

@Bean
public CacheManager cacheManager() {
    Duration duration = Duration.of(TIME_OUT, ChronoUnit.SECONDS);
    RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(lettuceConnectionFactory());
    RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer);
    RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig().entryTtl(duration).serializeValuesWith(pair);
    RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, defaultCacheConfig);
    return cacheManager;
}

@Bean("keyGenerator")
public KeyGenerator keyGenerator() {
    return (target, method, params) -> {
        StringBuilder sb = new StringBuilder();
        sb.append(target.getClass().getName());
        sb.append(method.getName());
        for (Object obj : params) {
            sb.append(obj.toString());
        }
        return sb.toString();
    };
}

@Override
public void setBeanClassLoader(ClassLoader classLoader) {
    this.classLoader = classLoader;
}

}

发送自 Windows 10 版邮件https://go.microsoft.com/fwlink/?LinkId=550986应用

发件人: 业余布道师 notifications@github.com 发送时间: Wednesday, November 28, 2018 1:42:36 PM 收件人: alibaba/fastjson 抄送: 程胜; Mention 主题: Re: [alibaba/fastjson] fastjson 无法反序列会redis存储的内容 (#2155)

@masterchengshenghttps://github.com/masterchengsheng 能否把出问题的完整JSON提供一下 我再测试一下

― You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/alibaba/fastjson/issues/2155#issuecomment-442326909, or mute the threadhttps://github.com/notifications/unsubscribe-auth/ASaHBdntfgkOkDSOMvUxblgg0eu3hnvIks5uziJMgaJpZM4Y1DTt.

9

这是我反序列化后的 没有问题啊

4

@masterchengsheng 兄弟儿,看不见你发的图...

8

7

@masterchengsheng 抱歉,实在无法复现你的问题

9

@masterchengsheng 能否跟到parser.parseObject(clazz, null);里面看看

3

@VictorZeng 我知道原因了 浪费您时间啦 BaseResult的 他没有加 set 方法

4

代码升级的时候 set方法被同时给删掉了 太尴尬了

5

@wenshao @masterchengsheng 可以close了