alibaba / alibaba/fastjson2

[BUG]java对象存在map套map且内层map是同一个对象,序列化结果带ref,反序列化失败

Open
#3,516 0 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
Java
Stars
4.4k
Forks
613
Avg merge
1d 22h
Merged PRs (30d)
6

Description

### 问题描述
如下代码,对象map套map,内层的reversePriceMap在多个外层对象中是同一个对象,序列化出来的字符串带有ref,但是在反序列化的时候失败。在fastjson中是直接抛异常,在fastjson2中是反序列化出来的内层对象是null

### 环境信息
*请填写以下信息:*

- OS信息: macos arm
- JDK信息: 1.8
- 版本信息:2.0.57

### 重现步骤
*如何操作可以重现该问题:*

1. 使用 `xxx.xxx` 方法
2. 输入 `...` 数据
3. 出现 `...` 错误
```java
public static void main(String[] args) {
List list = buildObject();
String json = JSON.toJSONString(list);
System.out.println(json);

List list2 = JSON.parseObject(json, new TypeReference>(){});
System.out.println(list2);
}

@Data
public static class RiskInfo{
private Map itemMap;
}

@Data
public static class Item {
private Long itemId;
private Map reversePriceMap;
}

@NotNull
private static List buildObject() {
RiskInfo riskInfo1 = new RiskInfo();
Item item = new Item();
item.setItemId(1L);
Map reversePriceMap = new HashMap<>();
reversePriceMap.put("1", 1L);
Map itemMap = new HashMap<>();
itemMap.put(item.getItemId(), item);
item.setReversePriceMap(reversePriceMap);
riskInfo1.setItemMap(itemMap);

RiskInfo riskInfo2 = new RiskInfo();
Item item2 = new Item();
item2.setItemId(2L);
item2.setReversePriceMap(reversePriceMap);
Map itemMap2 = new HashMap<>();
itemMap2.put(item2.getItemId(), item2);
riskInfo2.setItemMap(itemMap2);
// riskInfo2.setItemMap(itemMap);
return Lists.newArrayList(riskInfo1, riskInfo2);
}
```

### 期待的正确结果
[{"itemMap":{1:{"itemId":1,"reversePriceMap":{"1":1}}}},{"itemMap":{2:{"itemId":2,"reversePriceMap":{"$ref":"$[0].itemMap.reversePriceMap"}}}}]
[JsonRefTest2.RiskInfo(itemMap={1=JsonRefTest2.Item(itemId=1, reversePriceMap={1=1})}), JsonRefTest2.RiskInfo(itemMap={2=JsonRefTest2.Item(itemId=2, reversePriceMap={1=1})})]

### 实际输出
[{"itemMap":{1:{"itemId":1,"reversePriceMap":{"1":1}}}},{"itemMap":{2:{"itemId":2,"reversePriceMap":{"$ref":"$[0].itemMap.reversePriceMap"}}}}]
[JsonRefTest2.RiskInfo(itemMap={1=JsonRefTest2.Item(itemId=1, reversePriceMap={1=1})}), JsonRefTest2.RiskInfo(itemMap={2=JsonRefTest2.Item(itemId=2, reversePriceMap=null)})]

### 相关日志输出
暂无

#### 附加信息
*如果你还有其他需要提供的信息,可以在这里填写(可以提供截图、视频等)。*

Contributor guide

Open the contributing guide

Research direction

Start with the provided Java reproducer, focusing on JSON.toJSONString and JSON.parseObject when the nested reversePriceMap instance is shared. Trace reference handling during deserialization for the emitted $ref path, then verify that both nested maps are populated instead of leaving the second one null.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
backend-api-design
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.