This commit is contained in:
Looly 2021-09-14 09:58:21 +08:00
parent 46cffe4ed2
commit 1b0d5d2cf1
3 changed files with 114 additions and 25 deletions

View File

@ -3,7 +3,7 @@
-------------------------------------------------------------------------------------------------------------
# 5.7.13 (2021-09-13)
# 5.7.13 (2021-09-14)
### 🐣新特性
* 【core 】 CsvReadConfig增加trimField选项issue#I49M0C@Gitee
@ -17,6 +17,7 @@
* 【core 】 修复StrJoiner.append配置丢失问题issue#I49K1L@Gitee
* 【core 】 修复EscapeUtil特殊字符的hex长度不足导致的问题issue#I49JU8@Gitee
* 【core 】 修复UrlBuilder对Fragment部分编码问题issue#I49KAL@Gitee
* 【core 】 修复Enum转换的bugissue#I49VZB@Gitee
-------------------------------------------------------------------------------------------------------------

View File

@ -1,6 +1,7 @@
package cn.hutool.core.convert.impl;
import cn.hutool.core.convert.AbstractConverter;
import cn.hutool.core.convert.ConvertException;
import cn.hutool.core.lang.EnumItem;
import cn.hutool.core.lang.SimpleCache;
import cn.hutool.core.map.MapUtil;
@ -41,21 +42,30 @@ public class EnumConverter extends AbstractConverter<Object> {
protected Object convertInternal(Object value) {
Enum enumValue = tryConvertEnum(value, this.enumClass);
if (null == enumValue && false == value instanceof String) {
// 最后尝试valueOf转换
// 最后尝试先将value转StringvalueOf转换
enumValue = Enum.valueOf(this.enumClass, convertToStr(value));
}
if (null != enumValue) {
return enumValue;
}
throw new ConvertException("Can not convert {} to {}", value, this.enumClass);
}
@Override
public Class getTargetType() {
return this.enumClass;
}
/**
* 尝试找到类似转换的静态方法调用实现转换且优先使用<br>
* 约定枚举类应该提供 valueOf(String) valueOf(Integer)用于转换
* oriInt /name 转换托底
* 尝试转换转换规则为
* <ul>
* <li>如果实现{@link EnumItem}接口则调用fromInt或fromStr转换</li>
* <li>找到类似转换的静态方法调用实现转换且优先使用</li>
* <li>约定枚举类应该提供 valueOf(String) valueOf(Integer)用于转换</li>
* <li>oriInt /name 转换托底</li>
* </ul>
*
* @param value 被转换的值
* @param enumClass enum类
@ -67,7 +77,6 @@ public class EnumConverter extends AbstractConverter<Object> {
}
// EnumItem实现转换
Enum enumResult = null;
if (EnumItem.class.isAssignableFrom(enumClass)) {
final EnumItem first = (EnumItem) EnumUtil.getEnumAt(enumClass, 0);
if (null != first) {
@ -81,15 +90,19 @@ public class EnumConverter extends AbstractConverter<Object> {
// 用户自定义方法
// 查找枚举中所有返回值为目标枚举对象的方法如果发现方法参数匹配就执行之
try {
final Map<Class<?>, Method> methodMap = getMethodMap(enumClass);
if (MapUtil.isNotEmpty(methodMap)) {
final Class<?> valueClass = value.getClass();
for (Map.Entry<Class<?>, Method> entry : methodMap.entrySet()) {
if (ClassUtil.isAssignable(entry.getKey(), valueClass)) {
enumResult = ReflectUtil.invokeStatic(entry.getValue(), value);
return ReflectUtil.invokeStatic(entry.getValue(), value);
}
}
}
} catch (Exception ignore) {
//ignore
}
//oriInt 应该滞后使用 GB/T 2261.1-2003 性别编码为例对应整数并非连续数字会导致数字转枚举时失败
//0 - 未知的性别
@ -98,7 +111,7 @@ public class EnumConverter extends AbstractConverter<Object> {
//5 - 女性改()为男性
//6 - 男性改()为女性
//9 - 未说明的性别
if (null == enumResult) {
Enum enumResult = null;
if (value instanceof Integer) {
enumResult = EnumUtil.getEnumAt(enumClass, (Integer) value);
} else if (value instanceof String) {
@ -108,7 +121,7 @@ public class EnumConverter extends AbstractConverter<Object> {
//ignore
}
}
}
return enumResult;
}
@ -124,6 +137,6 @@ public class EnumConverter extends AbstractConverter<Object> {
.filter(m -> m.getReturnType() == enumClass)
.filter(m -> m.getParameterCount() == 1)
.filter(m -> false == "valueOf".equals(m.getName()))
.collect(Collectors.toMap(m -> m.getParameterTypes()[0], m -> m)));
.collect(Collectors.toMap(m -> m.getParameterTypes()[0], m -> m, (k1, k2) -> k1)));
}
}

View File

@ -0,0 +1,75 @@
import cn.hutool.core.convert.Convert;
import cn.hutool.json.JSONUtil;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.junit.Assert;
import org.junit.Test;
import java.util.stream.Stream;
/**
* https://gitee.com/dromara/hutool/issues/I49VZB
*/
public class IssueI49VZBTest {
public enum NBCloudKeyType {
/**
* 指纹-视频云
*/
fingerPrint,
/**
* 密码
*/
password,
/**
* 卡片
*/
card,
/**
* 临时密码
*/
snapKey;
public static NBCloudKeyType find(String value) {
return Stream.of(values()).filter(e -> e.getValue().equalsIgnoreCase(value)).findFirst()
.orElse(null);
}
public static NBCloudKeyType downFind(String keyType) {
if (fingerPrint.name().equals(keyType.toLowerCase())) {
return NBCloudKeyType.fingerPrint;
} else {
return find(keyType);
}
}
public String getValue() {
return super.toString().toLowerCase();
}
}
@Data
@EqualsAndHashCode(callSuper = false)
public static class UPOpendoor {
private String keyId;
private NBCloudKeyType type;
private String time;
private int result;
}
@Test
public void toBeanTest(){
String str = "{type: \"password\"}";
final UPOpendoor upOpendoor = JSONUtil.toBean(str, UPOpendoor.class);
Assert.assertEquals(NBCloudKeyType.password, upOpendoor.getType());
}
@Test
public void enumConvertTest(){
final NBCloudKeyType type = Convert.toEnum(NBCloudKeyType.class, "snapKey");
Assert.assertEquals(NBCloudKeyType.snapKey, type);
}
}