Hutool的方法BeanUtil.toBean报错Can not convert {} to class {}

1、问题描述

有以下一条Map结构的数据,sex字段的值是0

{
    name:"test",
    sex:"0"
}

对应的sex枚举

public enum SexEnum{
    MAN("0"),
    WOMAN("1");

    private String code;
    
    public SexEnum getByCode(String code) {
		for (SexEnumem : values()) {
			if (em.getCode().equals(code)) {
				return em;
			}
		}
		return null;
	}

}

调用BeanUtil.toBean,map转bean,报Can not convert 0 to class SexEnum

2、排查过程

debug toBean方法,最终定位到cn.hutool.core.convert.impl包下的EnumConverter枚举转换类的tryConvertEnum方法,如下

/**
	 * 尝试转换,转换规则为:
	 * <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类
	 * @return 对应的枚举值
	 */
	protected static Enum tryConvertEnum(Object value, Class enumClass) {
		if (value == null) {
			return null;
		}

		// EnumItem实现转换
		if (EnumItem.class.isAssignableFrom(enumClass)) {
			final EnumItem first = (EnumItem) EnumUtil.getEnumAt(enumClass, 0);
			if (null != first) {
				if (value instanceof Integer) {
					return (Enum) first.fromInt((Integer) value);
				} else if (value instanceof String) {
					return (Enum) first.fromStr(value.toString());
				}
			}
		}

		// 用户自定义方法
		// 查找枚举中所有返回值为目标枚举对象的方法,如果发现方法参数匹配,就执行之
		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)) {
						return ReflectUtil.invokeStatic(entry.getValue(), value);
					}
				}
			}
		} catch (Exception ignore) {
			//ignore
		}

		//oriInt 应该滞后使用 以 GB/T 2261.1-2003 性别编码为例,对应整数并非连续数字会导致数字转枚举时失败
		//0 - 未知的性别
		//1 - 男性
		//2 - 女性
		//5 - 女性改(变)为男性
		//6 - 男性改(变)为女性
		//9 - 未说明的性别
		Enum enumResult = null;
		if (value instanceof Integer) {
			enumResult = EnumUtil.getEnumAt(enumClass, (Integer) value);
		} else if (value instanceof String) {
			try {
				enumResult = Enum.valueOf(enumClass, (String) value);
			} catch (IllegalArgumentException e) {
				//ignore
			}
		}

		return enumResult;
	}

方法总结:属性值转枚举时,会优先获取返回值是该枚举类的静态方法,将调用此方法将属性值进行转换,如果枚举没提供以上方法,则调用枚举的valueOf方法,根据枚举名称转换。至此解决此问题的关键在于:1、枚举类中提供一个可行的静态方法可以转换属性值到枚举。2、属性值与枚举名称保持一致。

3、解决方法

结合上面的代码,可以发现提供的getByCode方法不是static方法,导致会调用valueOf方法,但是属性值(0)与枚举的名称(MAN)不一致导致报错;

因此,将方法改为static即可;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值