alibaba / alibaba/fastjson2

[BUG]2.0.53版本在jdk21下多构造函数时反序列化异常

Open
#3,104 2 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

### 问题描述

2.0.53版本在jdk21下多构造函数时反序列化异常

### 环境信息

- JDK:jdk-21.0.2
- fastjson:2.0.53

### 重现步骤

#### 【测试代码一】

```

com.alibaba.fastjson2
fastjson2
2.0.53

```
```
record Transform(Bridge bridge) {
public Transform(String from, String to) {
this(new Bridge(from, to));
}

public Transform(Bridge bridge) {
this.bridge = bridge;
}
}

record Bridge(String from, String to) {
}
```
```
@Test
public void testJDKRecord() throws Exception {
String json = JSON.toJSONString(new Transform("zhangsan", "lisi"));
System.out.println(json);
Transform transform = JSON.parseObject(json, Transform.class);
System.out.println(transform);
}
```
#### 【期望输出】
```
{"bridge":{"from":"zhangsan","to":"lisi"}}
Transform[bridge=Bridge[from=zhangsan, to=lisi]]
```
#### 【实际输出】
```
{"bridge":{"from":"zhangsan","to":"lisi"}}

com.alibaba.fastjson2.JSONException: invoke constructor error, public com.yiduo.jdk.example.Fastjson2ExampleTestCase$Transform(com.yiduo.jdk.example.Fastjson2ExampleTestCase$Bridge)

at com.alibaba.fastjson2.reader.ConstructorFunction.apply(ConstructorFunction.java:132)
at com.alibaba.fastjson2.reader.ConstructorFunction.apply(ConstructorFunction.java:15)
at com.alibaba.fastjson2.reader.ObjectReaderNoneDefaultConstructor.readObject(ObjectReaderNoneDefaultConstructor.java:351)
at com.alibaba.fastjson2.JSON.parseObject(JSON.java:864)
at com.yiduo.jdk.example.Fastjson2ExampleTestCase.testJDKRecord(Fastjson2ExampleTestCase.java:12)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
Caused by: java.lang.IllegalArgumentException: argument type mismatch
at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:65)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:502)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:486)
at com.alibaba.fastjson2.reader.ConstructorFunction.apply(ConstructorFunction.java:129)
... 7 more
Caused by: java.lang.ClassCastException: Cannot cast java.lang.String to com.yiduo.jdk.example.Fastjson2ExampleTestCase$Bridge
at java.base/java.lang.Class.cast(Class.java:4067)
at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)
... 10 more

```

#### 【测试代码二】

```
static class Transform2 {
private Bridge2 bridge;

public Transform2() {
}

public Transform2(String from, String to) {
this(new Bridge2(from, to));
}

public Transform2(Bridge2 bridge) {
this.bridge = bridge;
}

public Bridge2 getBridge() {
return bridge;
}

@Override
public String toString() {
return "Transform2{" +
"bridge=" + bridge +
'}';
}
}

static class Bridge2 {
private String from;
private String to;

public Bridge2() {
}

public Bridge2(String from, String to) {
this.from = from;
this.to = to;
}

public String getFrom() {
return from;
}

public String getTo() {
return to;
}

public void setFrom(String from) {
this.from = from;
}

public void setTo(String to) {
this.to = to;
}

@Override
public String toString() {
return "Bridge2{" +
"from='" + from + '\'' +
", to='" + to + '\'' +
'}';
}

}
```
```
@Test
public void testFastjson2Class() throws Exception {
String json = JSON.toJSONString(new Transform2("zhangsan", "lisi"));
System.out.println(json);
Transform2 transform = JSON.parseObject(json, Transform2.class);
System.out.println(transform);
}
```
#### 【期望输出】

```
{"bridge":{"from":"zhangsan","to":"lisi"}}

Transform2{bridge=Bridge2{from='zhangsan', to='lisi'}}
```

#### 【实际输出】
```
{"bridge":{"from":"zhangsan","to":"lisi"}}

Transform2{bridge=null}
```

Contributor guide

Open the contributing guide

Research direction

Reproduce the two examples on JDK 21 with fastjson 2.0.53, then inspect the stack-traced paths in ConstructorFunction.java and ObjectReaderNoneDefaultConstructor.java. The fix is done when both the record and ordinary-class examples deserialize without an argument-type error and produce the expected bridge values.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.