fastjson2
fastjson2 copied to clipboard
[BUG]JSONB开启FieldBased和NotWriteHashMapArrayListClassName序列化后再反序列化时存在问题
当存在一个默认值是不可变的 List 字段时存在问题(使用场景:dubbo 响应了一个 mybatis plus分页结果的Page对象)
public class Page<T> implements IPage<T> {
/**
* 查询数据列表
*/
protected List<T> records = Collections.emptyList();
}
java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
at com.alibaba.fastjson2.reader.ORG_1_1_UnmodifiableList.readJSONBObject(Unknown Source)
at com.alibaba.fastjson2.JSONB.parseObject(JSONB.java:799)
at com.alibaba.fastjson2.issues_2600.MybatisPlusPageTest.writeReade(MybatisPlusPageTest.java:70)
at com.alibaba.fastjson2.issues_2600.MybatisPlusPageTest.testUnmodifiableList(MybatisPlusPageTest.java:46)
at java.lang.reflect.Method.invoke(Method.java:498)
at java.util.ArrayList.forEach(ArrayList.java:1259)
at java.util.ArrayList.forEach(ArrayList.java:1259)
经检查是这段代码取了默认值,后面调用了它的 add 方法
com.alibaba.fastjson2.reader.ObjectReaderCreatorASM:3737
复现代码
package com.alibaba.fastjson2.issues_2600;
import com.alibaba.fastjson2.JSONB;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.internal.asm.MethodWriter;
import com.alibaba.fastjson2.reader.FieldReader;
import com.alibaba.fastjson2.reader.ObjectReaderCreatorASM;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.apache.dubbo.common.serialize.fastjson2.FastJson2ObjectInput;
import org.apache.dubbo.common.serialize.fastjson2.FastJson2ObjectOutput;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Type;
import java.util.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
/**
* @author 张治保
* @since 2024/6/12
*/
public class Issue2691 {
/**
* failed
* @see Page#records
* @see FastJson2ObjectOutput#writeObject(Object)
* @see FastJson2ObjectInput#readObject(Class)
* @see ObjectReaderCreatorASM#genReadFieldValueList(FieldReader, String, MethodWriter, int, int, int, int, int, Map, int, int, int, boolean, boolean, Class, Class, Type, long, Type, String, Integer)
*/
@Test
void testUnmodifiableList() {
UnmodifiableList list = new UnmodifiableList();
ArrayList<String> strings = new ArrayList<>();
strings.add("1");
list.setList(strings);
writeReade(list);
}
/**
* passed
*/
@Test
void testUnmodifiableMap(){
UnmodifiableMap map = new UnmodifiableMap();
Map<String,String> stringMap = new HashMap<>();
stringMap.put("1","1");
map.setMap(stringMap);
writeReade(map);
}
/**
* passed
*/
@Test
void testUnmodifiableSet(){
UnmodifiableSet set = new UnmodifiableSet();
Set<String> stringSet = new HashSet<>();
stringSet.add("1");
set.setSet(stringSet);
writeReade(set);
}
void writeReade(Object value){
byte[] bytes = JSONB.toBytes(
value,
JSONWriter.Feature.WriteClassName,
JSONWriter.Feature.FieldBased,
JSONWriter.Feature.NotWriteHashMapArrayListClassName
);
// readObject
Object result = JSONB.parseObject(
bytes,
value.getClass(),
JSONReader.Feature.FieldBased);
assertNotNull(result);
assertEquals(result,value);
}
@Getter
@Setter
@EqualsAndHashCode
@Accessors(chain = true)
private static class UnmodifiableList {
private List<String> list = Collections.emptyList();
}
@Getter
@Setter
@EqualsAndHashCode
@Accessors(chain = true)
private static class UnmodifiableSet {
private Set<String> set = Collections.emptySet();
}
@Getter
@Setter
@EqualsAndHashCode
@Accessors(chain = true)
private static class UnmodifiableMap {
private Map<String,String> map = Collections.emptyMap();
}
}