[BUG] JSONB 序列化多个自引用对象时,除第一个外 self 字段反序列化后为 null
- Dominant language
- Java
- Stars
- 4.4k
- Forks
- 613
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 6
Description
### 问题描述
JSONB 开启 ReferenceDetection 写引用时,若本次引用路径与上次相同,会折叠为 #-1(复用上一个引用目标)。但 ".." 是相对路径,含义是「当前对象自身」,两个相邻的 ".." 可能指向不同对象。
连续自引用被错误折叠后,反序列化时第二个引用会解析到第一个对象,导致对应字段变为 null。
### 环境信息
- OS信息: macOS Darwin 25.5.0
- JDK信息: Amazon Corretto 21.0.11
- 版本信息:Fastjson2 2.0.64
### 重现步骤
使用 JSONB.toBytes(..., JSONWriter.Feature.ReferenceDetection)(可叠加 FieldBased)序列化含多个自引用元素的列表
输入:ArrayList 中放入两个自引用 bean(self == this)
再经 JSONB.parseObject 反序列化后,第二个元素的 self 为 null(期望仍为自身)
```java
import com.alibaba.fastjson2.JSONB;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.TypeReference;
import java.util.ArrayList;
import java.util.List;
public class Demo {
public static class SelfBean {
public String name;
public SelfBean self;
}
public static void main(String[] args) {
List list = new ArrayList<>();
for (String name : new String[]{"a", "b"}) {
SelfBean bean = new SelfBean();
bean.name = name;
bean.self = bean;
list.add(bean);
}
byte[] bytes = JSONB.toBytes(
list,
JSONWriter.Feature.ReferenceDetection,
JSONWriter.Feature.FieldBased
);
List parsed = JSONB.parseObject(
bytes,
new TypeReference>() {}.getType(),
com.alibaba.fastjson2.JSONReader.Feature.FieldBased
);
// parsed.get(0).self == parsed.get(0) // OK
// parsed.get(1).self == null // BUG: should be parsed.get(1)
System.out.println(parsed.get(0).self == parsed.get(0));
System.out.println(parsed.get(1).self);
System.out.println(parsed.get(1).self == parsed.get(1));
}
}
```
### 期待的正确结果
列表中每个元素反序列化后仍满足 assertSame(bean, bean.self)。
相邻两个 ".." 引用不应被折叠为 #-1,应各自指向当前正在写入的对象。
### 相关日志输出
*请复制并粘贴任何相关的日志输出。*
#### 附加信息
*如果你还有其他需要提供的信息,可以在这里填写(可以提供截图、视频等)。*
Contributor guide
Research direction
Start at the JSONB.toBytes and JSONB.parseObject entry points and reproduce the issue with two self-referencing SelfBean instances in a list, using ReferenceDetection and FieldBased. Trace how consecutive ".." references are written and resolved; done means both deserialized elements satisfy assertSame(bean, bean.self) rather than the second self being null.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100