alibaba / alibaba/fastjson2

[BUG]对象包含有序集合,反序列化时乱序

Open
#2,736 1 comment 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

### 问题描述

包含TreeSet属性的对象,在序列化反序列化时TreeSet内值乱序

### 环境信息

- OS信息: [MacOs 13.41 Apple M1 16 GB]
- JDK信息: [Openjdk 1.8.0_401]
- 版本信息:[Fastjson2 2.0.51]

### 重现步骤
*如何操作可以重现该问题:*

1. 执行 `main` 方法

```java
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.annotation.JSONField;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Set;
import java.util.TreeSet;

import static com.alibaba.fastjson2.JSONReader.Feature.UseDefaultConstructorAsPossible;

@Data
public class TrainingDataParamsSet {

@ApiModelProperty(value = "算法")
private Set algorithms;

/**
* 平滑系数,lambda
*/
@ApiModelProperty(value = "平滑系数,lambda")
private Set algorithmParameters;

/**
* 阈值
*/
@ApiModelProperty(value = "阈值")
private Set thresholds;

/**
* 截断方式,1.去除-remove, 2-替换-replace
*/
@ApiModelProperty(value = "截断方式,1.去除-remove, 2-替换-replace")
private Set truncationMethods;

/**
* 截断率
*/
@ApiModelProperty(value = "截断率")
private Set truncationRates;

/**
* 步长
*/
@ApiModelProperty(value = "步长")
private Set steps;

/**
* 误差引入方式
*/
@ApiModelProperty(value = "误差引入方式")
private Set errorIntroductionMethods;

/**
* 系统误差-恒定误差
*/
@ApiModelProperty(value = "系统误差-恒定误差")
private Set systematicErrors;

/**
* 系统误差-比例误差
*/
@ApiModelProperty(value = "系统误差-比例误差")
private Set proportionalErrors;

/**
* 高斯分布标准差
*/
@ApiModelProperty(value = "高斯分布标准差")
private Set gaussianStds;

/**
* 高斯分布均值
*/
@ApiModelProperty(value = "高斯分布均值")
private Set gaussianMeans;

/**
* U型分布标准差
*/
@JSONField(name = "uShapedStds")
@ApiModelProperty(value = "U型分布标准差")
private Set uShapedStds;

/**
* U型分布均值
*/
@JSONField(name = "uShapedMeans")
@ApiModelProperty(value = "U型分布均值")
private Set uShapedMeans;

/**
* 均匀分布标准差
*/
@ApiModelProperty(value = "均匀分布标准差")
private Set uniformStds;

/**
* FPR1,falsePositiveRate,假阳率
*/
@ApiModelProperty(value = "FPR1,falsePositiveRate,假阳率")
private ValueRange fpr1s;

/**
* TPR1,truePositiveRate,真阳率
*/
@ApiModelProperty(value = "TPR1,truePositiveRate,真阳率")
private ValueRange tpr1s;

/**
* ANped(Adult Neutrophil per Erythroid cell division)骨髓中成人中性粒细胞与红细胞生成细胞之间的比率
*/
@JSONField(name = "aNped")
@ApiModelProperty(value = "ANped(Adult Neutrophil per Erythroid cell division)骨髓中成人中性粒细胞与红细胞生成细胞之间的比率")
private ValueRange aNpeds;

/**
* MNped(Mature Neutrophil per Erythroid cell division)骨髓中成熟中性粒细胞与红细胞生成细胞之间的比率
*/
@JSONField(name = "mNped")
@ApiModelProperty(value = "MNped(Mature Neutrophil per Erythroid cell division)骨髓中成熟中性粒细胞与红细胞生成细胞之间的比率")
private ValueRange mNpeds;

/**
* Nped95,95% 阴性预测值(95% NPV, NPed95)
*/
@ApiModelProperty(value = "Nped95,95% 阴性预测值(95% NPV, NPed95)")
private ValueRange nped95s;

/**
* 不稳定指标
*/
@ApiModelProperty(value = "不稳定指标")
private ValueRange instabilityIndices;

// 构造方法
public TrainingDataParamsSet() {
// 初始化所有 Set 类型属性为 TreeSet
this.algorithms = new TreeSet<>();
this.algorithmParameters = new TreeSet<>();
this.thresholds = new TreeSet<>();
this.truncationMethods = new TreeSet<>();
this.truncationRates = new TreeSet<>();
this.steps = new TreeSet<>();
this.errorIntroductionMethods = new TreeSet<>();
this.systematicErrors = new TreeSet<>();
this.proportionalErrors = new TreeSet<>();
this.gaussianStds = new TreeSet<>();
this.gaussianMeans = new TreeSet<>();
this.uShapedStds = new TreeSet<>();
this.uShapedMeans = new TreeSet<>();
this.uniformStds = new TreeSet<>();
this.fpr1s = new ValueRange();
this.tpr1s = new ValueRange();
this.aNpeds = new ValueRange();
this.mNpeds = new ValueRange();
this.nped95s = new ValueRange();
this.instabilityIndices = new ValueRange();
}

public static void main(String[] args) {
// 实例化 TrainingDataParamsSet 对象并设置属性值
TrainingDataParamsSet trainingDataParamsSet = new TrainingDataParamsSet();

// 设置属性值
trainingDataParamsSet.setSteps(new TreeSet<>(Arrays.asList(10, 30, 50, 70, 100, 130, 150, 200)));
trainingDataParamsSet.setAlgorithms(new TreeSet<>(Arrays.asList("ewma", "ma")));
trainingDataParamsSet.setUShapedStds(new TreeSet<>(Arrays.asList(new BigDecimal("0.33"), new BigDecimal("0.5"), new BigDecimal("1.5"), new BigDecimal("3.0"))));
trainingDataParamsSet.setUShapedMeans(new TreeSet<>(Arrays.asList(new BigDecimal("-0.5"), new BigDecimal("-0.3"), BigDecimal.ZERO, new BigDecimal("0.3"), new BigDecimal("0.5"))));
trainingDataParamsSet.setTruncationRates(new TreeSet<>(Arrays.asList(new BigDecimal("0.01"), new BigDecimal("0.02"), new BigDecimal("0.03"), new BigDecimal("0.04"), new BigDecimal("0.05"), new BigDecimal("0.1"), new BigDecimal("0.2"))));
trainingDataParamsSet.setTruncationMethods(new TreeSet<>(Arrays.asList(1, 2)));
trainingDataParamsSet.setErrorIntroductionMethods(new TreeSet<>(Arrays.asList("even", "gauss", "ratio", "stable", "u")));
String json = JSON.toJSONString(trainingDataParamsSet);
System.out.println(json);
TrainingDataParamsSet t = JSON.parseObject(json, TrainingDataParamsSet.class);
System.out.println("----");
System.out.println(t);
}

}

```

### 期待的正确结果
通过JSON.parseObject(json, TrainingDataParamsSet.class);得到的对象,里面的TreeSet实例是有序的

### 相关日志输出
{"aNped":{},"algorithmParameters":[],"algorithms":["ewma","ma"],"errorIntroductionMethods":["even","gauss","ratio","stable","u"],"fpr1s":{},"gaussianMeans":[],"gaussianStds":[],"instabilityIndices":{},"mNped":{},"nped95s":{},"proportionalErrors":[],"steps":[10,30,50,70,100,130,150,200],"systematicErrors":[],"thresholds":[],"tpr1s":{},"truncationMethods":[1,2],"truncationRates":[0.01,0.02,0.03,0.04,0.05,0.1,0.2],"uShapedMeans":[-0.5,-0.3,0,0.3,0.5],"uShapedStds":[0.33,0.5,1.5,3.0],"uniformStds":[]}
----
TrainingDataParamsSet(algorithms=[ma, ewma], algorithmParameters=[], thresholds=[], truncationMethods=[1, 2], truncationRates=[0.02, 0.1, 0.01, 0.05, 0.04, 0.03, 0.2], steps=[50, 130, 100, 70, 150, 200, 10, 30], errorIntroductionMethods=[gauss, even, u, stable, ratio], systematicErrors=[], proportionalErrors=[], gaussianStds=[], gaussianMeans=[], uShapedStds=[0.33, 1.5, 3.0, 0.5], uShapedMeans=[0, -0.5, -0.3, 0.5, 0.3], uniformStds=[], fpr1s=ValueRange(max=null, min=null), tpr1s=ValueRange(max=null, min=null), aNpeds=ValueRange(max=null, min=null), mNpeds=ValueRange(max=null, min=null), nped95s=ValueRange(max=null, min=null), instabilityIndices=ValueRange(max=null, min=null))

#### 附加信息

Contributor guide

Open the contributing guide

Research direction

Start with the provided main method and reproduce the behavior through JSON.parseObject(json, TrainingDataParamsSet.class). Trace how the Set fields are reconstructed during deserialization; done means the resulting TreeSet instances preserve sorted order for the shown values.

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
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.