diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/TypeConverterDelegate.java b/org.springframework.beans/src/main/java/org/springframework/beans/TypeConverterDelegate.java index f520d6fb654..650a6bf2972 100644 --- a/org.springframework.beans/src/main/java/org/springframework/beans/TypeConverterDelegate.java +++ b/org.springframework.beans/src/main/java/org/springframework/beans/TypeConverterDelegate.java @@ -196,8 +196,9 @@ class TypeConverterDelegate { ConversionService conversionService = this.propertyEditorRegistry.getConversionService(); if (editor == null && conversionService != null && convertedValue != null) { TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(convertedValue); - if (conversionService.canConvert(sourceTypeDesc, typeDescriptor)) { - return (T) conversionService.convert(convertedValue, sourceTypeDesc, typeDescriptor); + TypeDescriptor targetTypeDesc = typeDescriptor.forElementType(requiredType); + if (conversionService.canConvert(sourceTypeDesc, targetTypeDesc)) { + return (T) conversionService.convert(convertedValue, sourceTypeDesc, targetTypeDesc); } } @@ -205,8 +206,8 @@ class TypeConverterDelegate { if (editor != null || (requiredType != null && !ClassUtils.isAssignableValue(requiredType, convertedValue))) { if (requiredType != null && Collection.class.isAssignableFrom(requiredType) && convertedValue instanceof String && typeDescriptor.getMethodParameter() != null) { - Class elementType = GenericCollectionTypeResolver.getCollectionParameterType(typeDescriptor.getMethodParameter()); - if (elementType != null && Enum.class.isAssignableFrom(elementType)) { + Class elemType = GenericCollectionTypeResolver.getCollectionParameterType(typeDescriptor.getMethodParameter()); + if (elemType != null && Enum.class.isAssignableFrom(elemType)) { convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue); } } @@ -572,7 +573,8 @@ class TypeConverterDelegate { if (methodParam != null) { methodParam.increaseNestingLevel(); } - Object convertedElement = convertIfNecessary(indexedPropertyName, null, element, elementType); + Object convertedElement = convertIfNecessary( + indexedPropertyName, null, element, elementType, typeDescriptor); if (methodParam != null) { methodParam.decreaseNestingLevel(); } @@ -651,11 +653,11 @@ class TypeConverterDelegate { methodParam.increaseNestingLevel(); methodParam.setTypeIndexForCurrentLevel(0); } - Object convertedKey = convertIfNecessary(keyedPropertyName, null, key, keyType); + Object convertedKey = convertIfNecessary(keyedPropertyName, null, key, keyType, typeDescriptor); if (methodParam != null) { methodParam.setTypeIndexForCurrentLevel(1); } - Object convertedValue = convertIfNecessary(keyedPropertyName, null, value, valueType); + Object convertedValue = convertIfNecessary(keyedPropertyName, null, value, valueType, typeDescriptor); if (methodParam != null) { methodParam.decreaseNestingLevel(); } diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/TypeDescriptor.java b/org.springframework.core/src/main/java/org/springframework/core/convert/TypeDescriptor.java index 2ac6c7cd1ff..e5108a4ea1e 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/TypeDescriptor.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/TypeDescriptor.java @@ -103,8 +103,6 @@ public class TypeDescriptor { this.field = field; } - // protected constructors for subclasses - /** * Create a new type descriptor from a method or constructor parameter. *
Use this constructor when a target conversion point originates from a method parameter,
@@ -112,12 +110,23 @@ public class TypeDescriptor {
* @param methodParameter the MethodParameter to wrap
* @param type the specific type to expose (may be an array/collection element)
*/
- protected TypeDescriptor(MethodParameter methodParameter, Class> type) {
+ public TypeDescriptor(MethodParameter methodParameter, Class> type) {
Assert.notNull(methodParameter, "MethodParameter must not be null");
this.methodParameter = methodParameter;
this.type = type;
}
+ /**
+ * Create a new type descriptor for a field.
+ * Use this constructor when a target conversion point originates from a field.
+ * @param field the field to wrap
+ */
+ public TypeDescriptor(Field field, Class> type) {
+ Assert.notNull(field, "Field must not be null");
+ this.field = field;
+ this.type = type;
+ }
+
/**
* Internal constructor for a NULL descriptor.
*/
@@ -227,24 +236,43 @@ public class TypeDescriptor {
/**
* If this type is an array type or {@link Collection} type, returns the underlying element type.
- * Returns null if the type is neither an array or collection.
+ * Returns null if the type is neither an array or collection.
*/
public Class> getElementType() {
- return getElementTypeDescriptor().getType();
+ if (isArray()) {
+ return getArrayComponentType();
+ }
+ else if (isCollection()) {
+ return getCollectionElementType();
+ }
+ else {
+ return null;
+ }
}
/**
* Return the element type as a type descriptor.
*/
public TypeDescriptor getElementTypeDescriptor() {
- if (isArray()) {
- return TypeDescriptor.valueOf(getArrayComponentType());
+ return TypeDescriptor.valueOf(getElementType());
+ }
+
+ /**
+ * Create a copy of this type descriptor, preserving the context information
+ * but exposing the specified element type (e.g. an array/collection element).
+ * @param elementType the desired type to expose
+ * @return the type descriptor
+ */
+ public TypeDescriptor forElementType(Class> elementType) {
+ Assert.notNull(elementType, "Element type must not be null");
+ if (getType().equals(elementType)) {
+ return this;
}
- else if (isCollection()) {
- return TypeDescriptor.valueOf(getCollectionElementType());
+ else if (this.methodParameter != null) {
+ return new TypeDescriptor(this.methodParameter, elementType);
}
else {
- return TypeDescriptor.NULL;
+ return new TypeDescriptor(this.field, elementType);
}
}
diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/PropertyTypeDescriptor.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/PropertyTypeDescriptor.java
index 7f65be655c1..630579e6a52 100644
--- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/PropertyTypeDescriptor.java
+++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/PropertyTypeDescriptor.java
@@ -58,7 +58,7 @@ public class PropertyTypeDescriptor extends TypeDescriptor {
* @param methodParameter the target method parameter
* @param type the specific type to expose (may be an array/collection element)
*/
- public PropertyTypeDescriptor(PropertyDescriptor propertyDescriptor, MethodParameter methodParameter, Class type) {
+ public PropertyTypeDescriptor(PropertyDescriptor propertyDescriptor, MethodParameter methodParameter, Class> type) {
super(methodParameter, type);
this.propertyDescriptor = propertyDescriptor;
}