Skip to content

BeanUtil.copyProperties ConvertException #4245

@jekonhoo

Description

@jekonhoo
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Order {
    private Long orderId;
    private String orderNo;
    private List<OrderItem> orderItemList;
}

@Getter
@Setter(AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@NoArgsConstructor
public class OrderItem {
    private Long itemId;
    private String productName;
    private Integer quantity;
}

@Data
public class OrderDto {
    private Long orderId;
    private String orderNo;
    private List<OrderItemDto> orderItemList;
}

@Data
public class OrderItemDto {
    private Long itemId;
    private String productName;
    private Integer quantity;
}

void test() {

    Order order = new Order(
            1L,
            "01",
            new ArrayList<>()
    );
    order.getOrderItemList().add(
            new OrderItem(1L, "aa", 1)
    );

    OrderDto dto = new OrderDto();
    BeanUtil.copyProperties(
            order,
            OrderDto.class
    );
}

抛异常
cn.hutool.core.convert.ConvertException: Unsupported source type: class com.taos.OrderItem
异常代码

protected T convertInternal(Object value) {
	final Class<?>[] interfaces = this.beanClass.getInterfaces();
	for (Class<?> anInterface : interfaces) {
		if("cn.hutool.json.JSONBeanParser".equals(anInterface.getName())){
			final T obj = ReflectUtil.newInstanceIfPossible(this.beanClass);
			ReflectUtil.invoke(obj, "parse", value);
			return obj;
		}
	}
	if(value instanceof Map ||
			value instanceof ValueProvider ||
			BeanUtil.isBean(value.getClass())) {
		if(value instanceof Map && this.beanClass.isInterface()) {
			// 将Map动态代理为Bean
			return MapProxy.create((Map<?, ?>)value).toProxyBean(this.beanClass);
		}

		//限定被转换对象类型
		return BeanCopier.create(value, ReflectUtil.newInstanceIfPossible(this.beanClass), this.beanType, this.copyOptions).copy();
	} else if(value instanceof byte[]){
		// 尝试反序列化
		return ObjectUtil.deserialize((byte[])value);
	} else if(StrUtil.isEmptyIfStr(value)){
		// issue#3136
		return null;
	}

	throw new ConvertException("Unsupported source type: {}", value.getClass());
}

核心原因
BeanUtil.isBean(value.getClass())会检查必须有public field 或者 public setter
但是在执行拷贝的时候,protected setter 或者private field 是会被赋值的

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions