Convert single null argument to Optional.empty() in SpEL varargs expression
Prior to this commit, if a single null value was passed to a method with a varargs array of type java.util.Optional, that null value was passed unmodified. On the contrary, a null passed with additional values to such a method resulted in the null being converted to Optional.empty(). This commit ensures that a single null value is also converted to Optional.empty() for such SpEL expressions. Closes gh-27795
This commit is contained in:
parent
ad7cdc5ce9
commit
b2e94f611f
|
@ -20,6 +20,7 @@ import java.lang.reflect.Array;
|
|||
import java.lang.reflect.Executable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
|
@ -290,21 +291,29 @@ public abstract class ReflectionHelper {
|
|||
Object argument = arguments[varargsPosition];
|
||||
TypeDescriptor targetType = new TypeDescriptor(methodParam);
|
||||
TypeDescriptor sourceType = TypeDescriptor.forObject(argument);
|
||||
// If the argument is null or the argument type is equal to the varargs element type,
|
||||
// there is no need to convert it or wrap it in an array. For example, using
|
||||
// StringToArrayConverter to convert a String containing a comma would result in the
|
||||
// String being split and repackaged in an array when it should be used as-is.
|
||||
if (argument != null && !sourceType.equals(targetType.getElementTypeDescriptor())) {
|
||||
if (argument == null) {
|
||||
// Perform the equivalent of GenericConversionService.convertNullSource() for a single argument.
|
||||
if (targetType.getElementTypeDescriptor().getObjectType() == Optional.class) {
|
||||
arguments[varargsPosition] = Optional.empty();
|
||||
conversionOccurred = true;
|
||||
}
|
||||
}
|
||||
// If the argument type is equal to the varargs element type, there is no need to
|
||||
// convert it or wrap it in an array. For example, using StringToArrayConverter to
|
||||
// convert a String containing a comma would result in the String being split and
|
||||
// repackaged in an array when it should be used as-is.
|
||||
else if (!sourceType.equals(targetType.getElementTypeDescriptor())) {
|
||||
arguments[varargsPosition] = converter.convertValue(argument, sourceType, targetType);
|
||||
}
|
||||
// Possible outcomes of the above if-block:
|
||||
// Possible outcomes of the above if-else block:
|
||||
// 1) the input argument was null, and nothing was done.
|
||||
// 2) the input argument was correct type but not wrapped in an array, and nothing was done.
|
||||
// 3) the input argument was already compatible (i.e., array of valid type), and nothing was done.
|
||||
// 4) the input argument was the wrong type and got converted and wrapped in an array.
|
||||
// 2) the input argument was null; the varargs element type is Optional; and the argument was converted to Optional.empty().
|
||||
// 3) the input argument was correct type but not wrapped in an array, and nothing was done.
|
||||
// 4) the input argument was already compatible (i.e., array of valid type), and nothing was done.
|
||||
// 5) the input argument was the wrong type and got converted and wrapped in an array.
|
||||
if (argument != arguments[varargsPosition] &&
|
||||
!isFirstEntryInArray(argument, arguments[varargsPosition])) {
|
||||
conversionOccurred = true; // case 3
|
||||
conversionOccurred = true; // case 5
|
||||
}
|
||||
}
|
||||
// Otherwise, convert remaining arguments to the varargs element type.
|
||||
|
|
|
@ -302,10 +302,7 @@ public class MethodInvocationTests extends AbstractExpressionTests {
|
|||
evaluate("optionalVarargsMethod(2,3)", "[Optional[2], Optional[3]]", String.class);
|
||||
evaluate("optionalVarargsMethod('a',3.0d)", "[Optional[a], Optional[3.0]]", String.class);
|
||||
evaluate("optionalVarargsMethod(new String[]{'a','b','c'})", "[Optional[a], Optional[b], Optional[c]]", String.class);
|
||||
// The following should actually evaluate to [Optional.empty] instead of [null],
|
||||
// but ReflectionHelper.convertArguments() currently does not provide explicit
|
||||
// Optional support for a single argument passed to a varargs array.
|
||||
evaluate("optionalVarargsMethod(null)", "[null]", String.class);
|
||||
evaluate("optionalVarargsMethod(null)", "[Optional.empty]", String.class);
|
||||
evaluate("optionalVarargsMethod(null,'a')", "[Optional.empty, Optional[a]]", String.class);
|
||||
evaluate("optionalVarargsMethod('a',null,'b')", "[Optional[a], Optional.empty, Optional[b]]", String.class);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue