in dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/argument/GeneralTypeConverter.java [139:638]
private <T> Object doConvert(Object source, Class<T> targetClass) throws Exception {
if (source == null) {
return nullDefault(targetClass);
}
if (targetClass.isInstance(source)) {
return source;
}
if (targetClass == Optional.class) {
return Optional.of(source);
}
Class sourceClass = source.getClass();
if (sourceClass == Optional.class) {
source = ((Optional<?>) source).orElse(null);
if (source == null) {
return nullDefault(targetClass);
}
if (targetClass.isInstance(source)) {
return source;
}
}
Object target = customConvert(source, targetClass);
if (target != null) {
return target;
}
if (source instanceof CharSequence) {
String str = source.toString();
if (targetClass == String.class) {
return str;
}
if (str.isEmpty() || "null".equals(str) || "NULL".equals(str)) {
return emptyDefault(targetClass);
}
switch (targetClass.getName()) {
case "java.lang.Double":
case "double":
return Double.valueOf(str);
case "java.lang.Float":
case "float":
return Float.valueOf(str);
case "java.lang.Long":
case "long":
return isHexNumber(str) ? Long.decode(str) : Long.valueOf(str);
case "java.lang.Integer":
case "int":
return isHexNumber(str) ? Integer.decode(str) : Integer.valueOf(str);
case "java.lang.Short":
case "short":
return isHexNumber(str) ? Short.decode(str) : Short.valueOf(str);
case "java.lang.Character":
case "char":
if (str.length() == 1) {
return str.charAt(0);
}
throw new RestParameterException("Can not convert String(" + str + ") to char, must only 1 char");
case "java.lang.Byte":
case "byte":
return isHexNumber(str) ? Byte.decode(str) : Byte.valueOf(str);
case "java.lang.Boolean":
return toBoolean(str);
case "boolean":
return toBoolean(str) == Boolean.TRUE;
case "java.math.BigInteger":
return new BigInteger(str);
case "java.math.BigDecimal":
return new BigDecimal(str);
case "java.lang.Number":
return str.indexOf('.') == -1 ? doConvert(str, Long.class) : doConvert(str, Double.class);
case "java.util.Date":
return DateUtils.parse(str);
case "java.util.Calendar":
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(DateUtils.parse(str).getTime());
return cal;
case "java.sql.Timestamp":
return new Timestamp(DateUtils.parse(str).getTime());
case "java.time.Instant":
return DateUtils.parse(str).toInstant();
case "java.time.ZonedDateTime":
return toZonedDateTime(str);
case "java.time.LocalDate":
return toZonedDateTime(str).toLocalDate();
case "java.time.LocalTime":
return toZonedDateTime(str).toLocalTime();
case "java.time.LocalDateTime":
return toZonedDateTime(str).toLocalDateTime();
case "java.time.ZoneId":
return TimeZone.getTimeZone(str).toZoneId();
case "java.util.TimeZone":
return TimeZone.getTimeZone(str);
case "java.io.File":
return new File(str);
case "java.nio.file.Path":
return Paths.get(str);
case "java.nio.charset.Charset":
return Charset.forName(str);
case "java.net.InetAddress":
return InetAddress.getByName(str);
case "java.net.URI":
return new URI(str);
case "java.net.URL":
return new URL(str);
case "java.util.UUID":
return UUID.fromString(str);
case "java.util.Locale":
String[] parts = StringUtils.tokenize(str, '-', '_');
switch (parts.length) {
case 2:
return new Locale(parts[0], parts[1]);
case 3:
return new Locale(parts[0], parts[1], parts[2]);
default:
return new Locale(parts[0]);
}
case "java.util.Currency":
return Currency.getInstance(str);
case "java.util.regex.Pattern":
return Pattern.compile(str);
case "java.lang.Class":
return ClassUtils.loadClass(str);
case "[B":
return str.getBytes(UTF_8);
case "[C":
return str.toCharArray();
case "java.util.OptionalInt":
return OptionalInt.of(isHexNumber(str) ? Integer.decode(str) : Integer.parseInt(str));
case "java.util.OptionalLong":
return OptionalLong.of(isHexNumber(str) ? Long.decode(str) : Long.parseLong(str));
case "java.util.OptionalDouble":
return OptionalDouble.of(Double.parseDouble(str));
case "java.util.Properties":
Properties properties = new Properties();
properties.load(new StringReader(str));
return properties;
default:
}
if (targetClass.isEnum()) {
try {
return Enum.valueOf((Class<Enum>) targetClass, str);
} catch (Exception ignored) {
}
}
target = jsonToObject(str, targetClass);
if (target != null) {
return target;
}
if (targetClass.isArray()) {
List<String> list = tokenizeToList(str);
int n = list.size();
Class itemType = targetClass.getComponentType();
if (itemType == String.class) {
return list.toArray(StringUtils.EMPTY_STRING_ARRAY);
}
Object arr = Array.newInstance(itemType, n);
for (int i = 0; i < n; i++) {
Array.set(arr, i, doConvert(list.get(i), itemType));
}
return arr;
} else if (Collection.class.isAssignableFrom(targetClass)) {
target = convertCollection(tokenizeToList(str), targetClass);
if (target != null) {
return target;
}
} else if (Map.class.isAssignableFrom(targetClass)) {
target = convertMap(tokenizeToMap(str), targetClass);
if (target != null) {
return target;
}
}
} else if (source instanceof Number) {
Number num = (Number) source;
switch (targetClass.getName()) {
case "java.lang.String":
return source.toString();
case "java.lang.Double":
case "double":
return num.doubleValue();
case "java.lang.Float":
case "float":
return num.floatValue();
case "java.lang.Long":
case "long":
return num.longValue();
case "java.lang.Integer":
case "int":
return num.intValue();
case "java.lang.Short":
case "short":
return num.shortValue();
case "java.lang.Character":
case "char":
return (char) num.intValue();
case "java.lang.Byte":
case "byte":
return num.byteValue();
case "java.lang.Boolean":
case "boolean":
return toBoolean(num);
case "java.math.BigInteger":
return BigInteger.valueOf(num.longValue());
case "java.math.BigDecimal":
return BigDecimal.valueOf(num.doubleValue());
case "java.util.Date":
return new Date(num.longValue());
case "java.util.Calendar":
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(num.longValue());
return cal;
case "java.sql.Timestamp":
return new Timestamp(num.longValue());
case "java.time.Instant":
return Instant.ofEpochMilli(num.longValue());
case "java.time.ZonedDateTime":
return toZonedDateTime(num);
case "java.time.LocalDate":
return toZonedDateTime(num).toLocalDate();
case "java.time.LocalTime":
return toZonedDateTime(num).toLocalTime();
case "java.time.LocalDateTime":
return toZonedDateTime(num).toLocalDateTime();
case "java.util.TimeZone":
return toTimeZone(num.intValue());
case "[B":
return toBytes(num);
case "[C":
return new char[] {(char) num.intValue()};
case "java.util.OptionalInt":
return OptionalInt.of(num.intValue());
case "java.util.OptionalLong":
return OptionalLong.of(num.longValue());
case "java.util.OptionalDouble":
return OptionalDouble.of(num.doubleValue());
default:
}
if (targetClass.isEnum()) {
for (T e : targetClass.getEnumConstants()) {
if (((Enum) e).ordinal() == num.intValue()) {
return e;
}
}
}
} else if (source instanceof Date) {
Date date = (Date) source;
switch (targetClass.getName()) {
case "java.lang.String":
return DateUtils.format(date);
case "java.lang.Long":
case "long":
return date.getTime();
case "java.lang.Integer":
case "int":
return (int) (date.getTime() / 1000);
case "java.util.Calendar":
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(date.getTime());
return cal;
case "java.time.Instant":
return date.toInstant();
case "java.time.ZonedDateTime":
return toZonedDateTime(date.getTime());
case "java.time.LocalDate":
return toZonedDateTime(date.getTime()).toLocalDate();
case "java.time.LocalTime":
return toZonedDateTime(date.getTime()).toLocalTime();
case "java.time.LocalDateTime":
return toZonedDateTime(date.getTime()).toLocalDateTime();
default:
}
} else if (source instanceof TemporalAccessor) {
return doConvert(DateUtils.toDate((TemporalAccessor) source), targetClass);
} else if (source instanceof Enum) {
Enum en = (Enum) source;
if (targetClass == String.class) {
return en.toString();
}
if (targetClass == int.class || targetClass == Integer.class) {
return en.ordinal();
}
if (Number.class.isAssignableFrom(targetClass)) {
return doConvert(en.ordinal(), targetClass);
}
if (targetClass.isEnum()) {
return Enum.valueOf((Class<Enum>) targetClass, en.name());
}
} else if (source instanceof byte[]) {
byte[] bytes = (byte[]) source;
if (bytes.length == 0) {
return emptyDefault(targetClass);
}
switch (targetClass.getName()) {
case "java.lang.String":
return new String(bytes, UTF_8);
case "java.lang.Double":
case "double":
return ByteBuffer.wrap(bytes).getDouble();
case "java.lang.Float":
case "float":
return ByteBuffer.wrap(bytes).getFloat();
case "java.lang.Long":
case "long":
return ByteBuffer.wrap(bytes).getLong();
case "java.lang.Integer":
case "int":
return ByteBuffer.wrap(bytes).getInt();
case "java.lang.Short":
case "short":
return ByteBuffer.wrap(bytes).getShort();
case "java.lang.Character":
case "char":
return ByteBuffer.wrap(bytes).getChar();
case "java.lang.Byte":
case "byte":
return bytes[0];
case "java.lang.Boolean":
case "boolean":
return bytes[0] == (byte) 0 ? Boolean.FALSE : Boolean.TRUE;
case "java.math.BigInteger":
return new BigInteger(bytes);
case "java.util.Properties":
Properties properties = new Properties();
properties.load(new ByteArrayInputStream(bytes));
return properties;
default:
}
target = jsonToObject(new String(bytes, StandardCharsets.ISO_8859_1), targetClass);
if (target != null) {
return target;
}
}
if (targetClass.isArray()) {
if (targetClass == byte[].class) {
if (source instanceof InputStream) {
try (InputStream is = (InputStream) source) {
return StreamUtils.readBytes(is);
}
}
if (source instanceof FileUpload) {
try (InputStream is = ((FileUpload) source).inputStream()) {
return StreamUtils.readBytes(is);
}
}
if (source instanceof Character) {
char c = (Character) source;
return new byte[] {(byte) (c >> 8), (byte) c};
}
if (source instanceof Boolean) {
boolean b = (Boolean) source;
return new byte[] {b ? (byte) 1 : (byte) 0};
}
}
Class itemType = targetClass.getComponentType();
if (source instanceof Collection) {
Collection c = (Collection) source;
int i = 0;
Object arr = Array.newInstance(itemType, c.size());
for (Object item : c) {
Array.set(arr, i++, item == null ? null : doConvert(item, itemType));
}
return arr;
}
if (source instanceof Iterable) {
List list = new ArrayList();
for (Object item : (Iterable) source) {
list.add(item == null ? null : doConvert(item, itemType));
}
return list.toArray((Object[]) Array.newInstance(itemType, 0));
}
if (sourceClass.isArray()) {
int len = Array.getLength(source);
Object arr = Array.newInstance(itemType, len);
for (int i = 0; i < len; i++) {
Object item = Array.get(source, i);
Array.set(arr, i, item == null ? null : doConvert(item, itemType));
}
return arr;
}
Object arr = Array.newInstance(itemType, 1);
Array.set(arr, 0, doConvert(source, itemType));
return arr;
}
if (Collection.class.isAssignableFrom(targetClass)) {
target = convertCollection(toCollection(source), targetClass);
if (target != null) {
return target;
}
}
if (Map.class.isAssignableFrom(targetClass) && source instanceof Map) {
target = convertMap((Map) source, targetClass);
if (target != null) {
return target;
}
}
if (sourceClass.isArray()) {
if (Array.getLength(source) == 0) {
return nullDefault(targetClass);
}
return doConvert(Array.get(source, 0), targetClass);
}
if (source instanceof List) {
List list = (List) source;
if (list.isEmpty()) {
return nullDefault(targetClass);
}
return doConvert(list.get(0), targetClass);
}
if (source instanceof Iterable) {
Iterator it = ((Iterable) source).iterator();
if (!it.hasNext()) {
return nullDefault(targetClass);
}
return doConvert(it.next(), targetClass);
}
if (targetClass == String.class) {
if (sourceClass == HttpCookie.class) {
return ((HttpCookie) source).value();
}
if (source instanceof InputStream) {
try (InputStream is = (InputStream) source) {
return StreamUtils.toString(is);
}
}
if (source instanceof FileUpload) {
FileUpload fu = (FileUpload) source;
try (InputStream is = fu.inputStream()) {
String contentType = fu.contentType();
if (contentType != null) {
int index = contentType.lastIndexOf(HttpUtils.CHARSET_PREFIX);
if (index > 0) {
return StreamUtils.toString(
is,
Charset.forName(
contentType.substring(index + 8).trim()));
}
}
return StreamUtils.toString(is);
}
}
return source.toString();
}
if (!Modifier.isAbstract(targetClass.getModifiers())) {
try {
for (Constructor ct : targetClass.getConstructors()) {
if (ct.getParameterCount() == 1) {
if (ct.getParameterTypes()[0].isAssignableFrom(sourceClass)) {
return ct.newInstance(source);
}
}
}
} catch (Throwable ignored) {
}
}
if (sourceClass == String.class) {
try {
Method valueOf = targetClass.getMethod("valueOf", String.class);
//noinspection JavaReflectionInvocation
return valueOf.invoke(null, source);
} catch (Throwable ignored) {
}
return null;
}
try {
return httpJsonUtils.convertObject(source, targetClass);
} catch (Throwable t) {
String msg = "JSON convert value '{}' from type [{}] to type [{}] failed";
LOGGER.debug(msg, source, sourceClass, targetClass, t);
}
return null;
}