增加MapValueProviderRecordConverter并支持Record转换(issue#3985@Github)

This commit is contained in:
Looly
2025-07-02 10:41:21 +08:00
parent d5bb6b2adb
commit da7d6b9d81
5 changed files with 99 additions and 5 deletions

View File

@@ -0,0 +1,38 @@
package cn.hutool.core.bean.copier.provider;
import cn.hutool.core.bean.copier.ValueProvider;
import cn.hutool.core.convert.Convert;
import java.lang.reflect.Type;
import java.util.Map;
/**
* Map值提供者
*
* @author Looly
* @since 5.8.40
*/
@SuppressWarnings("rawtypes")
public class MapValueProvider implements ValueProvider<String> {
private final Map map;
/**
* 构造
*
* @param map map
*/
public MapValueProvider(final Map map) {
this.map = map;
}
@Override
public Object value(String key, Type valueType) {
return Convert.convert(valueType, map.get(key));
}
@Override
public boolean containsKey(String key) {
return map.containsKey(key);
}
}

View File

@@ -12,8 +12,8 @@ import java.util.Map;
* 抽象转换器提供通用的转换逻辑同时通过convertInternal实现对应类型的专属逻辑<br>
* 转换器不会抛出转换异常,转换失败时会返回{@code null}
*
* @param <T> 转换的目标类型
* @author Looly
*
*/
public abstract class AbstractConverter<T> implements Converter<T>, Serializable {
private static final long serialVersionUID = 1L;
@@ -22,7 +22,7 @@ public abstract class AbstractConverter<T> implements Converter<T>, Serializable
* 不抛异常转换<br>
* 当转换失败时返回默认值
*
* @param value 被转换的值
* @param value 被转换的值
* @param defaultValue 默认值
* @return 转换后的值
* @since 4.5.7
@@ -59,7 +59,7 @@ public abstract class AbstractConverter<T> implements Converter<T>, Serializable
return ((null == result) ? defaultValue : result);
} else {
throw new IllegalArgumentException(
StrUtil.format("Default value [{}]({}) is not the instance of [{}]", defaultValue, defaultValue.getClass(), targetType));
StrUtil.format("Default value [{}]({}) is not the instance of [{}]", defaultValue, defaultValue.getClass(), targetType));
}
}
@@ -98,9 +98,9 @@ public abstract class AbstractConverter<T> implements Converter<T>, Serializable
return value.toString();
} else if (ArrayUtil.isArray(value)) {
return ArrayUtil.toString(value);
} else if(CharUtil.isChar(value)) {
} else if (CharUtil.isChar(value)) {
//对于ASCII字符使用缓存加速转换减少空间创建
return CharUtil.toString((char)value);
return CharUtil.toString((char) value);
}
return value.toString();
}

View File

@@ -1,6 +1,7 @@
package cn.hutool.core.convert;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.RecordUtil;
import cn.hutool.core.convert.impl.*;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.lang.Opt;
@@ -346,6 +347,12 @@ public class ConverterRegistry implements Serializable {
return ReflectUtil.newInstanceIfPossible(rowType);
}
// record
// issue#3985@Github since 5.8.40
if(RecordUtil.isRecord(rowType)){
return (T) new RecordConverter(rowType).convert(value, defaultValue);
}
// 表示非需要特殊转换的对象
return null;
}

View File

@@ -0,0 +1,48 @@
package cn.hutool.core.convert.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.RecordUtil;
import cn.hutool.core.bean.copier.ValueProvider;
import cn.hutool.core.bean.copier.provider.BeanValueProvider;
import cn.hutool.core.bean.copier.provider.MapValueProvider;
import cn.hutool.core.convert.ConvertException;
import cn.hutool.core.convert.Converter;
import java.util.Map;
/**
* Record转换器
*
* @author looly
*/
public class RecordConverter implements Converter<Object> {
private final Class<?> recordClass;
/**
* 构造
* @param recordClass Record类
*/
public RecordConverter(Class<?> recordClass) {
this.recordClass = recordClass;
}
@SuppressWarnings("unchecked")
@Override
public Object convert(Object value, Object defaultValue) throws IllegalArgumentException {
ValueProvider<String> valueProvider = null;
if (value instanceof ValueProvider) {
valueProvider = (ValueProvider<String>) value;
} else if (value instanceof Map) {
valueProvider = new MapValueProvider((Map<String, ?>) value);
} else if (BeanUtil.isReadableBean(value.getClass())) {
valueProvider = new BeanValueProvider(value, false, false);
}
if (null != valueProvider) {
return RecordUtil.newInstance(recordClass, valueProvider);
}
throw new ConvertException("Unsupported source type: [{}] to [{}]", value.getClass(), recordClass);
}
}