in dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/argument/GeneralTypeConverter.java [640:780]
private Object doConvert(Object source, Type targetType) throws Exception {
if (targetType instanceof Class) {
return doConvert(source, (Class) targetType);
}
if (source == null) {
return nullDefault(getActualType(targetType));
}
if (source.getClass() == Optional.class) {
source = ((Optional<?>) source).orElse(null);
if (source == null) {
return nullDefault(getActualType(targetType));
}
}
if (source instanceof CharSequence) {
String str = source.toString();
if (str.isEmpty() || "null".equals(str) || "NULL".equals(str)) {
return emptyDefault(getActualType(targetType));
}
Object target = jsonToObject(str, targetType);
if (target != null) {
return target;
}
}
if (targetType instanceof ParameterizedType) {
ParameterizedType type = (ParameterizedType) targetType;
Type rawType = type.getRawType();
if (rawType instanceof Class) {
Class targetClass = (Class) rawType;
Type[] argTypes = type.getActualTypeArguments();
if (Collection.class.isAssignableFrom(targetClass)) {
Type itemType = getActualGenericType(argTypes[0]);
if (itemType instanceof Class && targetClass.isInstance(source)) {
boolean same = true;
Class<?> itemClass = (Class<?>) itemType;
for (Object item : (Collection) source) {
if (item != null && !itemClass.isInstance(item)) {
same = false;
break;
}
}
if (same) {
return source;
}
}
Collection items = toCollection(source);
Collection targetItems = createCollection(targetClass, items.size());
for (Object item : items) {
targetItems.add(doConvert(item, itemType));
}
return targetItems;
}
if (Map.class.isAssignableFrom(targetClass)) {
Type keyType = argTypes[0];
Type valueType = argTypes[1];
if (keyType instanceof Class && valueType instanceof Class && targetClass.isInstance(source)) {
boolean same = true;
Class<?> keyClass = (Class<?>) keyType;
Class<?> valueClass = (Class<?>) valueType;
for (Map.Entry entry : ((Map<Object, Object>) source).entrySet()) {
Object key = entry.getKey();
if (key != null && !keyClass.isInstance(key)) {
same = false;
break;
}
Object value = entry.getValue();
if (value != null && !valueClass.isInstance(value)) {
same = false;
break;
}
}
if (same) {
return source;
}
}
Class<?> mapValueClass = TypeUtils.getMapValueType(targetClass);
boolean multiValue = mapValueClass != null && Collection.class.isAssignableFrom(mapValueClass);
if (source instanceof CharSequence) {
source = tokenizeToMap(source.toString());
}
if (source instanceof Map) {
Map<?, ?> map = (Map) source;
Map targetMap = createMap(targetClass, map.size());
for (Map.Entry entry : map.entrySet()) {
Object key = doConvert(entry.getKey(), keyType);
if (multiValue) {
Collection items = toCollection(entry.getValue());
Collection targetItems = createCollection(mapValueClass, items.size());
for (Object item : items) {
targetItems.add(doConvert(item, valueType));
}
targetMap.put(key, targetItems);
} else {
targetMap.put(key, doConvert(entry.getValue(), valueType));
}
}
return targetMap;
}
}
if (targetClass == Optional.class) {
return Optional.ofNullable(doConvert(source, argTypes[0]));
}
}
} else if (targetType instanceof TypeVariable) {
return doConvert(source, ((TypeVariable<?>) targetType).getBounds()[0]);
} else if (targetType instanceof WildcardType) {
return doConvert(source, ((WildcardType) targetType).getUpperBounds()[0]);
} else if (targetType instanceof GenericArrayType) {
Type itemType = ((GenericArrayType) targetType).getGenericComponentType();
Class<?> itemClass = getActualType(itemType);
Collection items = toCollection(source);
Object target = Array.newInstance(itemClass, items.size());
int i = 0;
for (Object item : items) {
Array.set(target, i++, doConvert(item, itemType));
}
return target;
}
try {
return httpJsonUtils.convertObject(source, targetType);
} catch (Throwable t) {
String msg = "JSON convert value '{}' from type [{}] to type [{}] failed";
LOGGER.debug(msg, source, source.getClass(), targetType, t);
}
return null;
}