private Object doConvert()

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;
    }