mirror of https://github.com/alibaba/fastjson2.git
fixed: parse empty collection in kotlin (#1540)
Signed-off-by: Kraity <kraty@krait.cn>
This commit is contained in:
parent
f25d2e63a3
commit
37c584fbb9
|
|
@ -5,6 +5,7 @@ import com.alibaba.fastjson2.util.Fnv;
|
|||
import com.alibaba.fastjson2.util.GuavaSupport;
|
||||
import com.alibaba.fastjson2.util.TypeUtils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.*;
|
||||
|
|
@ -38,6 +39,7 @@ public final class ObjectReaderImplList
|
|||
final String itemClassName;
|
||||
final long itemClassNameHash;
|
||||
final Function builder;
|
||||
Object listSingleton;
|
||||
ObjectReader itemObjectReader;
|
||||
volatile boolean instanceError;
|
||||
|
||||
|
|
@ -164,14 +166,31 @@ public final class ObjectReaderImplList
|
|||
break;
|
||||
default:
|
||||
instanceClass = listClass;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (type == ObjectReaderImplList.CLASS_EMPTY_SET
|
||||
|| type == ObjectReaderImplList.CLASS_EMPTY_LIST
|
||||
) {
|
||||
return new ObjectReaderImplList(type, (Class) type, (Class) type, Object.class, null);
|
||||
switch (type.getTypeName()) {
|
||||
case "kotlin.collections.EmptySet":
|
||||
case "kotlin.collections.EmptyList": {
|
||||
Object empty;
|
||||
Class<?> clazz = (Class<?>) type;
|
||||
try {
|
||||
Field field = clazz.getField("INSTANCE");
|
||||
if (!field.isAccessible()) {
|
||||
field.setAccessible(true);
|
||||
}
|
||||
empty = field.get(null);
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
throw new IllegalStateException("Failed to get singleton of " + type, e);
|
||||
}
|
||||
return new ObjectReaderImplList(clazz, empty);
|
||||
}
|
||||
case "java.util.Collections$EmptySet": {
|
||||
return new ObjectReaderImplList((Class) type, Collections.emptySet());
|
||||
}
|
||||
case "java.util.Collections$EmptyList": {
|
||||
return new ObjectReaderImplList((Class) type, Collections.emptyList());
|
||||
}
|
||||
}
|
||||
|
||||
if (itemType == String.class && builder == null) {
|
||||
|
|
@ -185,6 +204,11 @@ public final class ObjectReaderImplList
|
|||
return new ObjectReaderImplList(type, listClass, instanceClass, itemType, builder);
|
||||
}
|
||||
|
||||
ObjectReaderImplList(Class listClass, Object listSingleton) {
|
||||
this(listClass, listClass, listClass, Object.class, null);
|
||||
this.listSingleton = listSingleton;
|
||||
}
|
||||
|
||||
public ObjectReaderImplList(Type listType, Class listClass, Class instanceType, Type itemType, Function builder) {
|
||||
this.listType = listType;
|
||||
this.listClass = listClass;
|
||||
|
|
@ -306,12 +330,8 @@ public final class ObjectReaderImplList
|
|||
return new TreeSet();
|
||||
}
|
||||
|
||||
if (instanceType == CLASS_EMPTY_LIST) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
if (instanceType == CLASS_EMPTY_SET) {
|
||||
return Collections.emptySet();
|
||||
if (listSingleton != null) {
|
||||
return listSingleton;
|
||||
}
|
||||
|
||||
if (instanceType != null) {
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ public final class ObjectReaderImplMap
|
|||
final Class instanceType;
|
||||
final long features;
|
||||
final Function builder;
|
||||
Object mapSingleton;
|
||||
volatile boolean instanceError;
|
||||
|
||||
public static ObjectReader of(Type fieldType, Class mapType, long features) {
|
||||
|
|
@ -87,9 +88,6 @@ public final class ObjectReaderImplMap
|
|||
case "java.util.Collections$SynchronizedSortedMap":
|
||||
instanceType = TreeMap.class;
|
||||
builder = (Function<SortedMap, SortedMap>) Collections::synchronizedSortedMap;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -137,6 +135,22 @@ public final class ObjectReaderImplMap
|
|||
builder = GuavaSupport.createConvertFunction(instanceType);
|
||||
instanceType = HashMap.class;
|
||||
break;
|
||||
case "kotlin.collections.EmptyMap": {
|
||||
Object mapSingleton;
|
||||
try {
|
||||
Field field = instanceType.getField("INSTANCE");
|
||||
if (!field.isAccessible()) {
|
||||
field.setAccessible(true);
|
||||
}
|
||||
mapSingleton = field.get(null);
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
throw new IllegalStateException("Failed to get singleton of " + instanceType, e);
|
||||
}
|
||||
return new ObjectReaderImplMap(instanceType, features, mapSingleton);
|
||||
}
|
||||
case "java.util.Collections$EmptyMap": {
|
||||
return new ObjectReaderImplMap(instanceType, features, Collections.EMPTY_MAP);
|
||||
}
|
||||
default:
|
||||
if (instanceType == JSONObject1O.class) {
|
||||
Class objectClass = CLASS_JSON_OBJECT_1x;
|
||||
|
|
@ -154,12 +168,16 @@ public final class ObjectReaderImplMap
|
|||
return Collections.singletonMap(entry.getKey(), entry.getValue());
|
||||
};
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return new ObjectReaderImplMap(fieldType, mapType, instanceType, features, builder);
|
||||
}
|
||||
|
||||
ObjectReaderImplMap(Class mapClass, long features, Object mapSingleton) {
|
||||
this(mapClass, mapClass, mapClass, features, null);
|
||||
this.mapSingleton = mapSingleton;
|
||||
}
|
||||
|
||||
ObjectReaderImplMap(Type fieldType, Class mapType, Class instanceType, long features, Function builder) {
|
||||
this.fieldType = fieldType;
|
||||
this.mapType = mapType;
|
||||
|
|
@ -193,8 +211,8 @@ public final class ObjectReaderImplMap
|
|||
return new JSONObject();
|
||||
}
|
||||
|
||||
if (instanceType == CLASS_EMPTY_MAP) {
|
||||
return Collections.emptyMap();
|
||||
if (mapSingleton != null) {
|
||||
return mapSingleton;
|
||||
}
|
||||
|
||||
if (instanceType == CLASS_EMPTY_SORTED_MAP) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
package com.alibaba.fastjson2.issues
|
||||
|
||||
import com.alibaba.fastjson2.JSON
|
||||
import com.alibaba.fastjson2.toJSONString
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Assertions.assertInstanceOf
|
||||
|
||||
class Issue1540 {
|
||||
|
||||
@Test
|
||||
fun test_map() {
|
||||
val map = emptyMap<Any?, Any?>()
|
||||
assertEquals("{}", map.toJSONString())
|
||||
assertInstanceOf(map::class.java, JSON.parseObject("{}", map::class.java))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_set() {
|
||||
val set = emptySet<Any?>()
|
||||
assertEquals("[]", set.toJSONString())
|
||||
assertInstanceOf(set::class.java, JSON.parseObject("[]", set::class.java))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_list() {
|
||||
val list = emptyList<Any?>()
|
||||
assertEquals("[]", list.toJSONString())
|
||||
assertInstanceOf(list::class.java, JSON.parseObject("[]", list::class.java))
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue