Expose convert(Object, TypeDescriptor) in ConversionService interface

Closes gh-25394
This commit is contained in:
Juergen Hoeller 2023-07-14 11:49:26 +02:00
parent 0ab94478fe
commit d24c131130
4 changed files with 24 additions and 34 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2017 the original author or authors. * Copyright 2002-2023 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -75,6 +75,23 @@ public interface ConversionService {
@Nullable @Nullable
<T> T convert(@Nullable Object source, Class<T> targetType); <T> T convert(@Nullable Object source, Class<T> targetType);
/**
* Convert the given {@code source} to the specified {@code targetType}.
* <p>Delegates to {@link #convert(Object, TypeDescriptor, TypeDescriptor)}
* and encapsulates the construction of the source type descriptor using
* {@link TypeDescriptor#forObject(Object)}.
* @param source the source object
* @param targetType the target type
* @return the converted value
* @throws ConversionException if a conversion exception occurred
* @throws IllegalArgumentException if targetType is {@code null}
* @since 6.1
*/
@Nullable
default Object convert(@Nullable Object source, TypeDescriptor targetType) {
return convert(source, TypeDescriptor.forObject(source), targetType);
}
/** /**
* Convert the given {@code source} to the specified {@code targetType}. * Convert the given {@code source} to the specified {@code targetType}.
* The TypeDescriptors provide additional context about the source and target locations * The TypeDescriptors provide additional context about the source and target locations

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2022 the original author or authors. * Copyright 2002-2023 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -31,7 +31,6 @@ import java.util.concurrent.CopyOnWriteArraySet;
import org.springframework.core.DecoratingProxy; import org.springframework.core.DecoratingProxy;
import org.springframework.core.ResolvableType; import org.springframework.core.ResolvableType;
import org.springframework.core.convert.ConversionException;
import org.springframework.core.convert.ConversionFailedException; import org.springframework.core.convert.ConversionFailedException;
import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.ConverterNotFoundException; import org.springframework.core.convert.ConverterNotFoundException;
@ -140,11 +139,7 @@ public class GenericConversionService implements ConfigurableConversionService {
@Override @Override
public boolean canConvert(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType) { public boolean canConvert(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType) {
Assert.notNull(targetType, "Target type to convert to cannot be null"); Assert.notNull(targetType, "Target type to convert to cannot be null");
if (sourceType == null) { return (sourceType == null || getConverter(sourceType, targetType) != null);
return true;
}
GenericConverter converter = getConverter(sourceType, targetType);
return (converter != null);
} }
/** /**
@ -160,15 +155,11 @@ public class GenericConversionService implements ConfigurableConversionService {
*/ */
public boolean canBypassConvert(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType) { public boolean canBypassConvert(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType) {
Assert.notNull(targetType, "Target type to convert to cannot be null"); Assert.notNull(targetType, "Target type to convert to cannot be null");
if (sourceType == null) { return (sourceType == null || getConverter(sourceType, targetType) == NO_OP_CONVERTER);
return true;
}
GenericConverter converter = getConverter(sourceType, targetType);
return (converter == NO_OP_CONVERTER);
} }
@Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override
@Nullable @Nullable
public <T> T convert(@Nullable Object source, Class<T> targetType) { public <T> T convert(@Nullable Object source, Class<T> targetType) {
Assert.notNull(targetType, "Target type to convert to cannot be null"); Assert.notNull(targetType, "Target type to convert to cannot be null");
@ -195,24 +186,6 @@ public class GenericConversionService implements ConfigurableConversionService {
return handleConverterNotFound(source, sourceType, targetType); return handleConverterNotFound(source, sourceType, targetType);
} }
/**
* Convenience operation for converting a source object to the specified targetType,
* where the target type is a descriptor that provides additional conversion context.
* Simply delegates to {@link #convert(Object, TypeDescriptor, TypeDescriptor)} and
* encapsulates the construction of the source type descriptor using
* {@link TypeDescriptor#forObject(Object)}.
* @param source the source object
* @param targetType the target type
* @return the converted value
* @throws ConversionException if a conversion exception occurred
* @throws IllegalArgumentException if targetType is {@code null},
* or sourceType is {@code null} but source is not {@code null}
*/
@Nullable
public Object convert(@Nullable Object source, TypeDescriptor targetType) {
return convert(source, TypeDescriptor.forObject(source), targetType);
}
@Override @Override
public String toString() { public String toString() {
return this.converters.toString(); return this.converters.toString();

View File

@ -106,7 +106,7 @@ public abstract class AbstractNamedValueMethodArgumentResolver implements SyncHa
} }
if (parameter != nestedParameter || !ClassUtils.isAssignableValue(parameter.getParameterType(), arg)) { if (parameter != nestedParameter || !ClassUtils.isAssignableValue(parameter.getParameterType(), arg)) {
arg = this.conversionService.convert(arg, TypeDescriptor.forObject(arg), new TypeDescriptor(parameter)); arg = this.conversionService.convert(arg, new TypeDescriptor(parameter));
// Check for null value after conversion of incoming argument value // Check for null value after conversion of incoming argument value
if (arg == null) { if (arg == null) {
if (namedValueInfo.defaultValue != null) { if (namedValueInfo.defaultValue != null) {

View File

@ -114,7 +114,7 @@ public abstract class AbstractNamedValueMethodArgumentResolver implements Handle
} }
if (parameter != nestedParameter || !ClassUtils.isAssignableValue(parameter.getParameterType(), arg)) { if (parameter != nestedParameter || !ClassUtils.isAssignableValue(parameter.getParameterType(), arg)) {
arg = this.conversionService.convert(arg, TypeDescriptor.forObject(arg), new TypeDescriptor(parameter)); arg = this.conversionService.convert(arg, new TypeDescriptor(parameter));
// Check for null value after conversion of incoming argument value // Check for null value after conversion of incoming argument value
if (arg == null) { if (arg == null) {
if (namedValueInfo.defaultValue != null) { if (namedValueInfo.defaultValue != null) {