|
|
@ -35,6 +35,7 @@ import org.springframework.core.convert.ConversionService; |
|
|
|
import org.springframework.core.convert.TypeDescriptor; |
|
|
|
import org.springframework.core.convert.TypeDescriptor; |
|
|
|
import org.springframework.lang.Nullable; |
|
|
|
import org.springframework.lang.Nullable; |
|
|
|
import org.springframework.util.ClassUtils; |
|
|
|
import org.springframework.util.ClassUtils; |
|
|
|
|
|
|
|
import org.springframework.util.CollectionUtils; |
|
|
|
import org.springframework.util.NumberUtils; |
|
|
|
import org.springframework.util.NumberUtils; |
|
|
|
import org.springframework.util.ReflectionUtils; |
|
|
|
import org.springframework.util.ReflectionUtils; |
|
|
|
import org.springframework.util.StringUtils; |
|
|
|
import org.springframework.util.StringUtils; |
|
|
@ -139,13 +140,17 @@ class TypeConverterDelegate { |
|
|
|
|
|
|
|
|
|
|
|
// Value not of required type?
|
|
|
|
// Value not of required type?
|
|
|
|
if (editor != null || (requiredType != null && !ClassUtils.isAssignableValue(requiredType, convertedValue))) { |
|
|
|
if (editor != null || (requiredType != null && !ClassUtils.isAssignableValue(requiredType, convertedValue))) { |
|
|
|
if (typeDescriptor != null && requiredType != null && Collection.class.isAssignableFrom(requiredType) && |
|
|
|
if (typeDescriptor != null && requiredType != null && Collection.class.isAssignableFrom(requiredType)) { |
|
|
|
convertedValue instanceof String text) { |
|
|
|
|
|
|
|
TypeDescriptor elementTypeDesc = typeDescriptor.getElementTypeDescriptor(); |
|
|
|
TypeDescriptor elementTypeDesc = typeDescriptor.getElementTypeDescriptor(); |
|
|
|
if (elementTypeDesc != null) { |
|
|
|
if (elementTypeDesc != null) { |
|
|
|
Class<?> elementType = elementTypeDesc.getType(); |
|
|
|
Class<?> elementType = elementTypeDesc.getType(); |
|
|
|
if (Class.class == elementType || Enum.class.isAssignableFrom(elementType)) { |
|
|
|
if (convertedValue instanceof String text) { |
|
|
|
convertedValue = StringUtils.commaDelimitedListToStringArray(text); |
|
|
|
if (Class.class == elementType || Enum.class.isAssignableFrom(elementType)) { |
|
|
|
|
|
|
|
convertedValue = StringUtils.commaDelimitedListToStringArray(text); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (editor == null && String.class != elementType) { |
|
|
|
|
|
|
|
editor = findDefaultEditor(Array.newInstance(elementType, 0).getClass()); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -166,11 +171,23 @@ class TypeConverterDelegate { |
|
|
|
} |
|
|
|
} |
|
|
|
else if (requiredType.isArray()) { |
|
|
|
else if (requiredType.isArray()) { |
|
|
|
// Array required -> apply appropriate conversion of elements.
|
|
|
|
// Array required -> apply appropriate conversion of elements.
|
|
|
|
if (convertedValue instanceof String text && Enum.class.isAssignableFrom(requiredType.getComponentType())) { |
|
|
|
if (convertedValue instanceof String text && |
|
|
|
|
|
|
|
Enum.class.isAssignableFrom(requiredType.getComponentType())) { |
|
|
|
convertedValue = StringUtils.commaDelimitedListToStringArray(text); |
|
|
|
convertedValue = StringUtils.commaDelimitedListToStringArray(text); |
|
|
|
} |
|
|
|
} |
|
|
|
return (T) convertToTypedArray(convertedValue, propertyName, requiredType.getComponentType()); |
|
|
|
return (T) convertToTypedArray(convertedValue, propertyName, requiredType.getComponentType()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
else if (convertedValue.getClass().isArray()) { |
|
|
|
|
|
|
|
if (Array.getLength(convertedValue) == 1) { |
|
|
|
|
|
|
|
convertedValue = Array.get(convertedValue, 0); |
|
|
|
|
|
|
|
standardConversion = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if (Collection.class.isAssignableFrom(requiredType)) { |
|
|
|
|
|
|
|
convertedValue = convertToTypedCollection(CollectionUtils.arrayToList(convertedValue), |
|
|
|
|
|
|
|
propertyName, requiredType, typeDescriptor); |
|
|
|
|
|
|
|
standardConversion = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
else if (convertedValue instanceof Collection<?> coll) { |
|
|
|
else if (convertedValue instanceof Collection<?> coll) { |
|
|
|
// Convert elements to target type, if determined.
|
|
|
|
// Convert elements to target type, if determined.
|
|
|
|
convertedValue = convertToTypedCollection(coll, propertyName, requiredType, typeDescriptor); |
|
|
|
convertedValue = convertToTypedCollection(coll, propertyName, requiredType, typeDescriptor); |
|
|
@ -181,10 +198,6 @@ class TypeConverterDelegate { |
|
|
|
convertedValue = convertToTypedMap(map, propertyName, requiredType, typeDescriptor); |
|
|
|
convertedValue = convertToTypedMap(map, propertyName, requiredType, typeDescriptor); |
|
|
|
standardConversion = true; |
|
|
|
standardConversion = true; |
|
|
|
} |
|
|
|
} |
|
|
|
if (convertedValue.getClass().isArray() && Array.getLength(convertedValue) == 1) { |
|
|
|
|
|
|
|
convertedValue = Array.get(convertedValue, 0); |
|
|
|
|
|
|
|
standardConversion = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (String.class == requiredType && ClassUtils.isPrimitiveOrWrapper(convertedValue.getClass())) { |
|
|
|
if (String.class == requiredType && ClassUtils.isPrimitiveOrWrapper(convertedValue.getClass())) { |
|
|
|
// We can stringify any primitive value...
|
|
|
|
// We can stringify any primitive value...
|
|
|
|
return (T) convertedValue.toString(); |
|
|
|
return (T) convertedValue.toString(); |
|
|
@ -501,12 +514,11 @@ class TypeConverterDelegate { |
|
|
|
|
|
|
|
|
|
|
|
Collection<Object> convertedCopy; |
|
|
|
Collection<Object> convertedCopy; |
|
|
|
try { |
|
|
|
try { |
|
|
|
if (approximable) { |
|
|
|
if (approximable && requiredType.isInstance(original)) { |
|
|
|
convertedCopy = CollectionFactory.createApproximateCollection(original, original.size()); |
|
|
|
convertedCopy = CollectionFactory.createApproximateCollection(original, original.size()); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
else { |
|
|
|
convertedCopy = (Collection<Object>) |
|
|
|
convertedCopy = CollectionFactory.createCollection(requiredType, original.size()); |
|
|
|
ReflectionUtils.accessibleConstructor(requiredType).newInstance(); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
catch (Throwable ex) { |
|
|
|
catch (Throwable ex) { |
|
|
@ -576,12 +588,11 @@ class TypeConverterDelegate { |
|
|
|
|
|
|
|
|
|
|
|
Map<Object, Object> convertedCopy; |
|
|
|
Map<Object, Object> convertedCopy; |
|
|
|
try { |
|
|
|
try { |
|
|
|
if (approximable) { |
|
|
|
if (approximable && requiredType.isInstance(original)) { |
|
|
|
convertedCopy = CollectionFactory.createApproximateMap(original, original.size()); |
|
|
|
convertedCopy = CollectionFactory.createApproximateMap(original, original.size()); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
else { |
|
|
|
convertedCopy = (Map<Object, Object>) |
|
|
|
convertedCopy = CollectionFactory.createMap(requiredType, original.size()); |
|
|
|
ReflectionUtils.accessibleConstructor(requiredType).newInstance(); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
catch (Throwable ex) { |
|
|
|
catch (Throwable ex) { |
|
|
|