[BUG] 2.0.64 序列化带 @JsonFormat(shape = STRING) 的 BigDecimal 时生成非法 JSON
- 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
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