alibaba / alibaba/fastjson2

[BUG] 2.0.64 序列化带 @JsonFormat(shape = STRING) 的 BigDecimal 时生成非法 JSON

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

### 问题描述

从 `com.alibaba:fastjson:2.0.47` 升级到 `2.0.64` 后,使用 Fastjson 1.x 兼容包序列化带 Jackson `@JsonFormat(shape = JsonFormat.Shape.STRING)` 的 `BigDecimal` 字段时,数值 `0.47` 被输出为未加引号的 `string0`,生成非法 JSON;随后调用 `JSON.parseObject` 报 `illegal input error`。回退到 2.0.47 后恢复正常。

### 环境信息

- OS 信息:Windows
- JDK 信息:JDK 1.8.0_162
- Spring Boot:2.3.12.RELEASE
- 版本信息:Fastjson 2.0.64(`com.alibaba:fastjson` 兼容包)

### 重现步骤

1. 引入依赖:

```xml

com.alibaba
fastjson
2.0.64

```

2. 运行以下最小复现代码:

```java
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.annotation.JsonFormat;

import java.math.BigDecimal;

public class FastjsonJacksonFormatBigDecimalTest {

public static class Bean {
@JsonFormat(shape = JsonFormat.Shape.STRING)
public BigDecimal examScore = new BigDecimal("0.47");
}

public static void main(String[] args) {
String json = JSON.toJSONString(new Bean());
System.out.println(json);
JSON.parseObject(json, Bean.class);
}
}
```

### 实际结果

Fastjson 2.0.64 输出:

```text
{"examScore":string0}
```

随后解析失败:

```text
com.alibaba.fastjson.JSONException: illegal input error, offset 14, character s, line 1, column 14, fastjson-version 2.0.64
```

### 期待的正确结果

应生成合法 JSON,并保持 Jackson 注解指定的字符串形式:

```json
{"examScore":"0.47"}
```

### 版本对比与临时规避

- 2.0.47 输出 `{"examScore":"0.47"}`,可以正常反序列化。
- 2.0.64 输出 `{"examScore":string0}`,生成非法 JSON。
- 2.0.64 添加 JVM 参数 `-Dfastjson2.useJacksonAnnotation=false` 后输出 `{"examScore":0.47}` 并可解析,但会全局关闭 Jackson 注解兼容,不能作为通用解决办法。
- 当前临时回退并固定在 2.0.47。

### 初步定位

初步对比源码发现,`BeanUtils.processJacksonJsonFormat(FieldInfo, Annotation)` 对 `JsonFormat.Shape.STRING` 的处理发生了变化:

- 2.0.47 使用 `JSONWriter.Feature.WriteNonStringValueAsString`;
- 2.0.64 设置 `fieldInfo.format = "string"`。

对 `BigDecimal` 字段,`"string"` 似乎被当作数值格式化模式,最终把 `0.47` 格式化为未加引号的 `string0`。请确认这是否为回归问题,并协助修复。

Contributor guide

Open the contributing guide

Research direction

Start with BeanUtils.processJacksonJsonFormat(FieldInfo, Annotation) and compare its handling of JsonFormat.Shape.STRING between versions 2.0.47 and 2.0.64. Use the provided FastjsonJacksonFormatBigDecimalTest reproduction, then add or run a regression test showing that BigDecimal 0.47 is serialized as "0.47" and can be parsed back successfully.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
backend-api-design
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.