alibaba / alibaba/fastjson2

[BUG] JSONB 序列化多个自引用对象时,除第一个外 self 字段反序列化后为 null

Open
#7,746 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

### 问题描述

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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.