开发者社区 问答 正文

fastjson2 版本2.0.5x序列化错误如:{"id":,,,"name":"name_14}

使用版本fastjson2版本2.0.5x,多版本切换都存在序列化错误问题
问题描述:在springboot2.7.18版本中,使用junit测试用例测试序列化一个大对象Set users= new HashSet<>();当数量小1000序列化相等稳定,比较正常。超过5000开始不稳定,超过10000必现序列化不符合预期结果。
期望结果如:[{"id":7075,"name":"name_7074"}, {"id":5192,"name":"name_5191"}]
而不稳定的情况下,会出现部分TmpUser序列化成了{"id":,,"name":"name_6154"}、{"id":,,,"name":"name_14643"}
image.png 截图是序列化后存入redis的截图。本地打印输出:还有这种现象 {"id":1,,,"name":"name11210"}
id值是等于name
之后的数字-1。测试附加上去的,name正常,id错误。没能序列化成功,变成多种多样的带逗号,且无规律,有纯2个逗号,有3个逗号,有第一个数字后带逗号"id":1,,,
本地相关关键点日志输出:
image.png
红框中输出是:[{"id":,,"name":"name_1143"},{"id":1ya,"name":"name_17651"}]。id更错乱,17651数字变成了1ya.
尝试过的方法:
1、TmpUser主动在字段上加@JSONField 和不加@JSONField都存在该现象
2、尝试关闭 ASM 生成:System.setProperty("fastjson2.asm.enable", "false");
也尝试spring配置文件增加fastjson2.asm.enable=false
均无效。

本地纯Mian调用,序列化正常,只有在springboot环境存在该问题。

测试对象User
@Data
@AllArgsConstructor
public class TmpUser implements Serializable {

private static final long serialVersionUID = -6720446582694992657L;
@JSONField(name = "id", ordinal = 1)
private Long id;
@JSONField(name = "name", ordinal = 2)
private String name;

}
调用序列化方法
public static String toJson(Object object) {
if (object == null) {
return null;
}
try {
// 添加诊断:谁在调用?
String jsonString = JSON.toJSONString(object);
System.out.println("=== toJson called by ==="+jsonString);
// Thread.dumpStack();
return jsonString;
// return JSON.toJSONString(object);
} catch (Exception e) {
LogUtils.error(log, e, "缓存JSON序列化失败, 对象类型: {}", object.getClass().getName());
throw new BizException(BaseErrorCode.JSON_EXCEPTION, "序列化失败: " + e.getMessage());
}
}

springboot中单测试代码如下
public void addBatchTest(){
System.setProperty("fastjson2.asm.enable", "false");
String key = prefixKey+"batchSet2";
redisSetCacheUtil.delete(key);
Set users = new HashSet<>();
for(long i=1;i<=20000;i++){
users.add(new TmpUser(i,"name_"+i));
}
redisSetCacheUtil.addCacheSet(key,users,10,TimeUnit.MINUTES);
// Assert.assertEquals(11000,redisSetCacheUtil.sizeFromSet(key).longValue());
Set tmpUsers1 = redisSetCacheUtil.randomMembersFromSet(key, 2, false, 10, TimeUnit.MINUTES, TmpUser.class);
// Assert.assertEquals(2,tmpUsers1.size());
System.out.println("JsonUtils-toJson:"+ JsonCacheUtils.toJson(tmpUsers1));
// Assert.assertEquals(11000-2,redisSetCacheUtil.sizeFromSet(key).longValue());
for(TmpUser u:tmpUsers1){
System.out.println("uid:"+u.getId());
}
}
RedissetCacheUtil 相关代码
/**

 * 批量添加(分批 100 条插入,避免大对象阻塞)
 */
public Long addCacheSet(String key, Set<?> dataSet, long timeout, TimeUnit unit) {
    if(!validateKey(key)||CollectionUtils.isEmpty(dataSet)){
        return 0L;
    }
    SetOperations<String, String> setOps = stringRedisTemplate.opsForSet();

    //批操作,一批插入100条
    int batchSize = 100;
    int size = dataSet.size();
    List<String> jsonList = JsonCacheUtils.toJsonList(new ArrayList<>(dataSet));
    for(String s:jsonList){
        System.out.println(s);
    }
    long totalCount=0;
    if (size <= batchSize) {
        Long count;
        count = setOps.add(key, jsonList.toArray(new String[0]));
        totalCount = count!=null?count:0;
    } else {
        for (int i = 0; i < jsonList.size(); i += batchSize) {
            Long count;
            int end = Math.min(i + batchSize, jsonList.size());
            count = setOps.add(key, jsonList.subList(i, end).toArray(new String[0]));
            totalCount+=count!=null?count:0;
        }
    }
    if (timeout > 0 && unit!=null) {
        stringRedisTemplate.expire(key, timeout, unit);
    }
    return totalCount;
}

JsonCacheUtils工具类代码
protected static List toJsonList(Collection data) {
if (data == null || data.isEmpty()) {
return Collections.emptyList();
}
return data.stream()
.filter(Objects::nonNull)
.map(JsonCacheUtils::toJson)
.collect(Collectors.toList());
}

public static String toJson(Object object) {
    if (object == null) {
        return null;
    }
    try {
        // 添加诊断:谁在调用?
        String jsonString = JSON.toJSONString(object);
        System.out.println("=== toJson called by ==="+jsonString);

// Thread.dumpStack();
return jsonString;
// return JSON.toJSONString(object);
} catch (Exception e) {
LogUtils.error(log, e, "缓存JSON序列化失败, 对象类型: {}", object.getClass().getName());
throw new BizException(BaseErrorCode.JSON_EXCEPTION, "序列化失败: " + e.getMessage());
}
}

展开
收起
游客aqlkjjc2adgy4 2025-09-15 16:25:47 13 分享 版权
0 条回答
写回答
取消 提交回答