[BUG] testParseObjectWithImmutableCollectionField
问题描述
简要描述您碰到的问题。 序列化Immutable的collection类直接crash
环境信息
请填写以下信息:
- OS信息: [Ubuntu 22.04.3 LTS]
- JDK信息: [openjdk 11.0.22 2024-01-16]
- 版本信息:[Fastjson 2.0.49 兼容1.x.x]
重现步骤
Test case
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.parser.ParserConfig;
import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import static org.junit.Assert.assertEquals;
public class Test512 {
@Test
public void testParseObjectWithImmutableCollectionField() {
String jsonString = "{\"collectionField\": [1, 2, 3]}";
class ImmutableCollectionExample {
private final Collection<Integer> collectionField;
public ImmutableCollectionExample(Collection<Integer> collectionField) {
this.collectionField = Collections.unmodifiableCollection(new ArrayList<>(collectionField));
}
public Collection<Integer> getCollectionField() {
return collectionField;
}
}
try {
InputStream inputStream = new ByteArrayInputStream(jsonString.getBytes(StandardCharsets.UTF_8));
ImmutableCollectionExample result = JSON.parseObject(inputStream, StandardCharsets.UTF_8,
ImmutableCollectionExample.class, new ParserConfig(), Feature.SupportArrayToBean, Feature.DisableCircularReferenceDetect);
assertEquals(Arrays.asList(1, 2, 3), new ArrayList<>(result.getCollectionField()));
} catch (IOException e) {
// Handle or log the exception
}
}
}
期待的正确结果
希望能够正常反序列化
相关日志输出
*java.lang.UnsupportedOperationException at java.base/java.util.Collections$UnmodifiableCollection.add(Collections.java:1067) at com.alibaba.fastjson2.reader.FieldReaderCollectionMethodReadOnly.accept(FieldReaderCollectionMethodReadOnly.java:93) at com.alibaba.fastjson2.reader.ObjectReaderNoneDefaultConstructor.readObject(ObjectReaderNoneDefaultConstructor.java:356) at com.alibaba.fastjson.JSON.parseObject(JSON.java:666) at com.alibaba.fastjson.JSON.parseObject(JSON.java:687) at Test512.testParseObjectWithImmutableCollectionField(Test512.java:37) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) at java.base/java.lang.reflect.Method.invoke(Method.java:578) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306) at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63) at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329) at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293) at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306) at org.junit.runners.ParentRunner.run(ParentRunner.java:413) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69) at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38) at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11) at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35) at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232) at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55) *
看异常的堆栈,应该是该集合是只读不可写的,所以你可以换成别的可写的集合。
感觉和fastjson初始化的方法有关系,如果是直接把填好值的数组给到类的构造器就可以,fastjson貌似是先构造数组然后向数组内填值所以遇到不可以改变的集合就会报错,感觉这种情况有时候会碰到,就是有时候我需要的就是一个初始化时就确定好不变的集合
感觉和fastjson初始化的方法有关系,如果是直接把填好值的数组给到类的构造器就可以,fastjson貌似是先构造数组然后向数组内填值所以遇到不可以改变的集合就会报错,感觉这种情况有时候会碰到,就是有时候我需要的就是一个初始化时就确定好不变的集合
你的想法是好的。但是我还是建议你先在 getter 方法处返回为不可变集合,先解决眼下的问题。
https://oss.sonatype.org/content/repositories/snapshots/com/alibaba/fastjson2/fastjson2/2.0.50-SNAPSHOT/ 问题已修复,请帮忙用2.0.50-SNAPSHOT版本验证,2.0.50版本预计在5月12日前发布
https://oss.sonatype.org/content/repositories/snapshots/com/alibaba/fastjson2/fastjson2/2.0.50-SNAPSHOT/ 问题已修复,请帮忙用2.0.50-SNAPSHOT版本验证,2.0.50版本预计在5月12日前发布
经过检验可以顺利反序列化,辛苦wenshao
https://github.com/alibaba/fastjson2/releases/tag/2.0.50 2.0.50已发布,请用新版本