mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-07-21 15:09:48 +08:00
fix code
This commit is contained in:
@@ -36,7 +36,7 @@ public class ConcurrentLinkedHashSet<E> extends SetFromMap<E> {
|
||||
* 构造
|
||||
*/
|
||||
public ConcurrentLinkedHashSet() {
|
||||
super(new ConcurrentLinkedHashMap.Builder<E, Boolean>().build());
|
||||
super(new ConcurrentLinkedHashMap.Builder<E, Boolean>().maximumWeightedCapacity(64).build());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -46,7 +46,10 @@ public class ConcurrentLinkedHashSet<E> extends SetFromMap<E> {
|
||||
* @param initialCapacity 初始大小
|
||||
*/
|
||||
public ConcurrentLinkedHashSet(final int initialCapacity) {
|
||||
super(new ConcurrentLinkedHashMap.Builder<E, Boolean>().initialCapacity(initialCapacity).build());
|
||||
super(new ConcurrentLinkedHashMap.Builder<E, Boolean>()
|
||||
.initialCapacity(initialCapacity)
|
||||
.maximumWeightedCapacity(initialCapacity)
|
||||
.build());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,6 +61,7 @@ public class ConcurrentLinkedHashSet<E> extends SetFromMap<E> {
|
||||
public ConcurrentLinkedHashSet(final int initialCapacity, final int concurrencyLevel) {
|
||||
super(new ConcurrentLinkedHashMap.Builder<E, Boolean>()
|
||||
.initialCapacity(initialCapacity)
|
||||
.maximumWeightedCapacity(initialCapacity)
|
||||
.concurrencyLevel(concurrencyLevel)
|
||||
.build());
|
||||
}
|
||||
|
@@ -56,7 +56,7 @@ public abstract class AbstractConverter implements Converter, Serializable {
|
||||
// 尝试强转
|
||||
if (targetClass.isInstance(value)) {
|
||||
// 除Map外,已经是目标类型,不需要转换(Map类型涉及参数类型,需要单独转换)
|
||||
return CastUtil.castTo(targetClass, value);
|
||||
return value;
|
||||
}
|
||||
return convertInternal(targetClass, value);
|
||||
}
|
||||
|
@@ -17,19 +17,13 @@
|
||||
package org.dromara.hutool.core.convert;
|
||||
|
||||
import org.dromara.hutool.core.bean.BeanUtil;
|
||||
import org.dromara.hutool.core.bean.RecordUtil;
|
||||
import org.dromara.hutool.core.convert.impl.*;
|
||||
import org.dromara.hutool.core.convert.impl.BeanConverter;
|
||||
import org.dromara.hutool.core.lang.Opt;
|
||||
import org.dromara.hutool.core.reflect.ConstructorUtil;
|
||||
import org.dromara.hutool.core.reflect.TypeReference;
|
||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||
import org.dromara.hutool.core.reflect.kotlin.KClassUtil;
|
||||
import org.dromara.hutool.core.util.ObjUtil;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
@@ -164,7 +158,7 @@ public class CompositeConverter extends RegisterConverter {
|
||||
}
|
||||
|
||||
// 特殊类型转换,包括Collection、Map、强转、Array等
|
||||
final T result = convertSpecial(type, rawType, value, defaultValue);
|
||||
final T result = (T) SpecialConverter.getInstance().convert(type, rawType, value);
|
||||
if (null != result) {
|
||||
return result;
|
||||
}
|
||||
@@ -177,101 +171,4 @@ public class CompositeConverter extends RegisterConverter {
|
||||
// 无法转换
|
||||
throw new ConvertException("Can not convert from {}: [{}] to [{}]", value.getClass().getName(), value, type.getTypeName());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------- Private method start
|
||||
|
||||
/**
|
||||
* 特殊类型转换<br>
|
||||
* 包括:
|
||||
*
|
||||
* <pre>
|
||||
* Collection
|
||||
* Map
|
||||
* 强转(无需转换)
|
||||
* 数组
|
||||
* </pre>
|
||||
*
|
||||
* @param <T> 转换的目标类型(转换器转换到的类型)
|
||||
* @param type 类型
|
||||
* @param rawType 原始类型
|
||||
* @param value 值
|
||||
* @param defaultValue 默认值
|
||||
* @return 转换后的值
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T convertSpecial(final Type type, final Class<T> rawType, final Object value, final T defaultValue) {
|
||||
if (null == rawType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 日期、java.sql中的日期以及自定义日期统一处理
|
||||
if (Date.class.isAssignableFrom(rawType)) {
|
||||
return DateConverter.INSTANCE.convert(type, value, defaultValue);
|
||||
}
|
||||
|
||||
// 集合转换(含有泛型参数,不可以默认强转)
|
||||
if (Collection.class.isAssignableFrom(rawType)) {
|
||||
return (T) CollectionConverter.INSTANCE.convert(type, value, (Collection<?>) defaultValue);
|
||||
}
|
||||
|
||||
// Map类型(含有泛型参数,不可以默认强转)
|
||||
if (Map.class.isAssignableFrom(rawType)) {
|
||||
return (T) MapConverter.INSTANCE.convert(type, value, (Map<?, ?>) defaultValue);
|
||||
}
|
||||
|
||||
// issue#I6SZYB Entry类(含有泛型参数,不可以默认强转)
|
||||
if (Map.Entry.class.isAssignableFrom(rawType)) {
|
||||
return (T) EntryConverter.INSTANCE.convert(type, value);
|
||||
}
|
||||
|
||||
// 默认强转
|
||||
if (rawType.isInstance(value)) {
|
||||
return (T) value;
|
||||
}
|
||||
|
||||
// 原始类型转换
|
||||
if (rawType.isPrimitive()) {
|
||||
return PrimitiveConverter.INSTANCE.convert(type, value, defaultValue);
|
||||
}
|
||||
|
||||
// 数字类型转换
|
||||
if (Number.class.isAssignableFrom(rawType)) {
|
||||
return NumberConverter.INSTANCE.convert(type, value, defaultValue);
|
||||
}
|
||||
|
||||
// 枚举转换
|
||||
if (rawType.isEnum()) {
|
||||
return EnumConverter.INSTANCE.convert(type, value, defaultValue);
|
||||
}
|
||||
|
||||
// 数组转换
|
||||
if (rawType.isArray()) {
|
||||
return ArrayConverter.INSTANCE.convert(type, value, defaultValue);
|
||||
}
|
||||
|
||||
// Record
|
||||
if (RecordUtil.isRecord(rawType)) {
|
||||
return (T) RecordConverter.INSTANCE.convert(type, value);
|
||||
}
|
||||
|
||||
// Kotlin Bean
|
||||
if (KClassUtil.isKotlinClass(rawType)) {
|
||||
return (T) KBeanConverter.INSTANCE.convert(type, value);
|
||||
}
|
||||
|
||||
// issue#I7FQ29 Class
|
||||
if ("java.lang.Class".equals(rawType.getName())) {
|
||||
return (T) ClassConverter.INSTANCE.convert(type, value);
|
||||
}
|
||||
|
||||
// 空值转空Bean
|
||||
if (ObjUtil.isEmpty(value)) {
|
||||
// issue#3649 空值转空对象,则直接实例化
|
||||
return ConstructorUtil.newInstanceIfPossible(rawType);
|
||||
}
|
||||
|
||||
// 表示非需要特殊转换的对象
|
||||
return null;
|
||||
}
|
||||
// ----------------------------------------------------------- Private method end
|
||||
}
|
||||
|
@@ -25,7 +25,7 @@ import java.util.Set;
|
||||
|
||||
/**
|
||||
* 用户自定义转换器<br>
|
||||
* 通过自定义实现{@link PredicateConverter},可以通过{@link PredicateConverter#test(Object)} 检查目标类型是否匹配<br>
|
||||
* 通过自定义实现{@link MatcherConverter},可以通过{@link MatcherConverter#match(Type, Class, Object)} 检查目标类型是否匹配<br>
|
||||
* 如果匹配,则直接转换,否则使用默认转换器转换。
|
||||
*
|
||||
* @author Looly
|
||||
@@ -41,37 +41,38 @@ public class CustomConverter implements Converter, Serializable {
|
||||
/**
|
||||
* 静态初始化器,由JVM来保证线程安全
|
||||
*/
|
||||
private static final RegisterConverter INSTANCE = new RegisterConverter();
|
||||
private static final CustomConverter INSTANCE = new CustomConverter();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得单例的 RegisterConverter
|
||||
* 获得单例的 CustomConverter
|
||||
*
|
||||
* @return RegisterConverter
|
||||
* @return CustomConverter
|
||||
*/
|
||||
public static RegisterConverter getInstance() {
|
||||
public static CustomConverter getInstance() {
|
||||
return CustomConverter.SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户自定义类型转换器
|
||||
*/
|
||||
private volatile Set<PredicateConverter> converterSet;
|
||||
private volatile Set<MatcherConverter> converterSet;
|
||||
|
||||
@Override
|
||||
public Object convert(final Type targetType, final Object value) throws ConvertException {
|
||||
final Converter customConverter = getCustomConverter(targetType);
|
||||
final Converter customConverter = getCustomConverter(targetType, value);
|
||||
return null == customConverter ? null : customConverter.convert(targetType, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得匹配类型的自定义转换器
|
||||
*
|
||||
* @param type 类型
|
||||
* @param type 类型
|
||||
* @param value 被转换的值
|
||||
* @return 转换器
|
||||
*/
|
||||
public Converter getCustomConverter(final Type type) {
|
||||
return getConverterFromSet(this.converterSet, type);
|
||||
public Converter getCustomConverter(final Type type, final Object value) {
|
||||
return getConverterFromSet(this.converterSet, type, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,7 +81,7 @@ public class CustomConverter implements Converter, Serializable {
|
||||
* @param converter 转换器
|
||||
* @return ConverterRegistry
|
||||
*/
|
||||
public CustomConverter add(final PredicateConverter converter) {
|
||||
public CustomConverter add(final MatcherConverter converter) {
|
||||
if (null == this.converterSet) {
|
||||
synchronized (this) {
|
||||
if (null == this.converterSet) {
|
||||
@@ -98,7 +99,7 @@ public class CustomConverter implements Converter, Serializable {
|
||||
* @param type 类型
|
||||
* @return 转换器
|
||||
*/
|
||||
private static Converter getConverterFromSet(final Set<? extends PredicateConverter> converterSet, final Type type) {
|
||||
return StreamUtil.of(converterSet).filter((predicate) -> predicate.test(type)).findFirst().orElse(null);
|
||||
private static Converter getConverterFromSet(final Set<? extends MatcherConverter> converterSet, final Type type, final Object value) {
|
||||
return StreamUtil.of(converterSet).filter((predicate) -> predicate.match(type, value)).findFirst().orElse(null);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Hutool Team and hutool.cn
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.core.convert;
|
||||
|
||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* 带有匹配的转换器<br>
|
||||
* 判断目标对象是否满足条件,满足则转换,否则跳过<br>
|
||||
* 实现此接口同样可以不判断断言而直接转换
|
||||
*
|
||||
* @author Looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public interface MatcherConverter extends Converter {
|
||||
|
||||
/**
|
||||
* 判断需要转换的对象是否匹配当前转换器,满足则转换,否则跳过
|
||||
*
|
||||
* @param targetType 转换的目标类型,不能为{@code null}
|
||||
* @param rawType 目标原始类型,当targetType为Class时,和此参数一致,不能为{@code null}
|
||||
* @param value 需要转换的值
|
||||
* @return 是否匹配
|
||||
*/
|
||||
boolean match(Type targetType, Class<?> rawType, Object value);
|
||||
|
||||
/**
|
||||
* 判断需要转换的对象是否匹配当前转换器,满足则转换,否则跳过
|
||||
*
|
||||
* @param targetType 转换的目标类型
|
||||
* @param value 需要转换的值
|
||||
* @return 是否匹配
|
||||
*/
|
||||
default boolean match(final Type targetType, final Object value) {
|
||||
return match(targetType, TypeUtil.getClass(targetType), value);
|
||||
}
|
||||
}
|
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Hutool Team and hutool.cn
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.core.convert;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* 断言转换器<br>
|
||||
* 判断目标对象是否满足断言,满足则转换,否则跳过<br>
|
||||
* 实现此接口同样可以不判断断言而直接转换
|
||||
*
|
||||
* @author Looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public interface PredicateConverter extends Converter, Predicate<Type> {
|
||||
}
|
@@ -170,11 +170,12 @@ public class RegisterConverter implements Converter, Serializable {
|
||||
final Map<Class<?>, Converter> defaultConverterMap = new SafeConcurrentHashMap<>(64);
|
||||
|
||||
// 包装类转换器
|
||||
defaultConverterMap.put(Character.class, new CharacterConverter());
|
||||
defaultConverterMap.put(Boolean.class, new BooleanConverter());
|
||||
defaultConverterMap.put(AtomicBoolean.class, new AtomicBooleanConverter());// since 3.0.8
|
||||
defaultConverterMap.put(CharSequence.class, new StringConverter());
|
||||
defaultConverterMap.put(String.class, new StringConverter());
|
||||
defaultConverterMap.put(Character.class, CharacterConverter.INSTANCE);
|
||||
defaultConverterMap.put(Boolean.class, BooleanConverter.INSTANCE);
|
||||
defaultConverterMap.put(AtomicBoolean.class, AtomicBooleanConverter.INSTANCE);// since 3.0.8
|
||||
final StringConverter stringConverter = new StringConverter();
|
||||
defaultConverterMap.put(CharSequence.class, stringConverter);
|
||||
defaultConverterMap.put(String.class, stringConverter);
|
||||
|
||||
// URI and URL
|
||||
defaultConverterMap.put(URI.class, new URIConverter());
|
||||
|
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Hutool Team and hutool.cn
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.core.convert;
|
||||
|
||||
import org.dromara.hutool.core.convert.impl.*;
|
||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||
import org.dromara.hutool.core.stream.StreamUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 特殊类型转换器,如果不符合特殊类型,则返回{@code null}继续其它转换规则<br>
|
||||
* 对于特殊对象(如集合、Map、Enum、数组)等的转换器,实现转换<br>
|
||||
* 注意:此类中的转换器查找是通过遍历方式
|
||||
*
|
||||
* @author Looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class SpecialConverter implements Converter, Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例 没有绑定关系,而且只有被调用到才会装载,从而实现了延迟加载
|
||||
*/
|
||||
private static class SingletonHolder {
|
||||
/**
|
||||
* 静态初始化器,由JVM来保证线程安全
|
||||
*/
|
||||
private static final SpecialConverter INSTANCE = new SpecialConverter();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得单例的 CustomConverter
|
||||
*
|
||||
* @return CustomConverter
|
||||
*/
|
||||
public static SpecialConverter getInstance() {
|
||||
return SpecialConverter.SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 类型转换器集合<br>
|
||||
* 此集合初始化后不再加入新值,因此单例使用线程安全
|
||||
*/
|
||||
private final Set<MatcherConverter> converterSet;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*/
|
||||
private SpecialConverter() {
|
||||
final Set<MatcherConverter> converterSet = new LinkedHashSet<>(64);
|
||||
|
||||
// 集合转换(含有泛型参数,不可以默认强转)
|
||||
converterSet.add(CollectionConverter.INSTANCE);
|
||||
// Map类型(含有泛型参数,不可以默认强转)
|
||||
converterSet.add(MapConverter.INSTANCE);
|
||||
// issue#I6SZYB Entry类(含有泛型参数,不可以默认强转)
|
||||
converterSet.add(EntryConverter.INSTANCE);
|
||||
// 默认强转
|
||||
converterSet.add(CastConverter.INSTANCE);
|
||||
// 日期、java.sql中的日期以及自定义日期统一处理
|
||||
converterSet.add(DateConverter.INSTANCE);
|
||||
// 原始类型转换
|
||||
converterSet.add(PrimitiveConverter.INSTANCE);
|
||||
// 数字类型转换
|
||||
converterSet.add(NumberConverter.INSTANCE);
|
||||
// 枚举转换
|
||||
converterSet.add(EnumConverter.INSTANCE);
|
||||
// 数组转换
|
||||
converterSet.add(ArrayConverter.INSTANCE);
|
||||
// Record
|
||||
converterSet.add(RecordConverter.INSTANCE);
|
||||
// Kotlin Bean
|
||||
converterSet.add(KBeanConverter.INSTANCE);
|
||||
// issue#I7FQ29 Class
|
||||
converterSet.add(ClassConverter.INSTANCE);
|
||||
// // 空值转空Bean
|
||||
converterSet.add(EmptyBeanConverter.INSTANCE);
|
||||
|
||||
this.converterSet = converterSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convert(final Type targetType, final Object value) throws ConvertException {
|
||||
return convert(targetType, TypeUtil.getClass(targetType), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换值
|
||||
*
|
||||
* @param targetType 目标类型
|
||||
* @param rawType 目标原始类型(即目标的Class)
|
||||
* @param value 被转换的值
|
||||
* @return 转换后的值,如果无转换器,返回{@code null}
|
||||
* @throws ConvertException 转换异常,即找到了对应的转换器,但是转换失败
|
||||
*/
|
||||
public Object convert(final Type targetType, final Class<?> rawType, final Object value) throws ConvertException {
|
||||
final Converter converter = getConverter(targetType, rawType, value);
|
||||
return null == converter ? null : converter.convert(targetType, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得匹配的转换器
|
||||
*
|
||||
* @param type 类型
|
||||
* @param rawType 目标类型的Class
|
||||
* @param value 被转换的值
|
||||
* @return 转换器
|
||||
*/
|
||||
public Converter getConverter(final Type type, final Class<?> rawType, final Object value) {
|
||||
return getConverterFromSet(this.converterSet, type, rawType, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从指定集合中查找满足条件的转换器
|
||||
*
|
||||
* @param type 类型
|
||||
* @return 转换器
|
||||
*/
|
||||
private static Converter getConverterFromSet(final Set<? extends MatcherConverter> converterSet, final Type type, final Class<?> rawType, final Object value) {
|
||||
return StreamUtil.of(converterSet).filter((predicate) -> predicate.match(type, rawType, value)).findFirst().orElse(null);
|
||||
}
|
||||
}
|
@@ -22,6 +22,7 @@ import org.dromara.hutool.core.collection.ListUtil;
|
||||
import org.dromara.hutool.core.collection.iter.IterUtil;
|
||||
import org.dromara.hutool.core.convert.AbstractConverter;
|
||||
import org.dromara.hutool.core.convert.ConvertUtil;
|
||||
import org.dromara.hutool.core.convert.MatcherConverter;
|
||||
import org.dromara.hutool.core.io.SerializeUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.core.text.split.SplitUtil;
|
||||
@@ -29,6 +30,7 @@ import org.dromara.hutool.core.util.ByteUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@@ -38,7 +40,7 @@ import java.util.List;
|
||||
*
|
||||
* @author Looly
|
||||
*/
|
||||
public class ArrayConverter extends AbstractConverter {
|
||||
public class ArrayConverter extends AbstractConverter implements MatcherConverter {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
@@ -67,6 +69,11 @@ public class ArrayConverter extends AbstractConverter {
|
||||
this.ignoreElementError = ignoreElementError;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean match(final Type targetType, final Class<?> rawType, final Object value) {
|
||||
return rawType.isArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object convertInternal(final Class<?> targetClass, final Object value) {
|
||||
final Class<?> targetComponentType;
|
||||
|
@@ -30,6 +30,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
public class AtomicBooleanConverter extends AbstractConverter {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 单例
|
||||
*/
|
||||
public static final AtomicBooleanConverter INSTANCE = new AtomicBooleanConverter();
|
||||
|
||||
@Override
|
||||
protected AtomicBoolean convertInternal(final Class<?> targetClass, final Object value) {
|
||||
if (value instanceof Boolean) {
|
||||
|
@@ -35,6 +35,11 @@ import org.dromara.hutool.core.util.BooleanUtil;
|
||||
public class BooleanConverter extends AbstractConverter {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 单例
|
||||
*/
|
||||
public static final BooleanConverter INSTANCE = new BooleanConverter();
|
||||
|
||||
@Override
|
||||
protected Boolean convertInternal(final Class<?> targetClass, final Object value) {
|
||||
if (value instanceof Number) {
|
||||
|
@@ -16,23 +16,34 @@
|
||||
|
||||
package org.dromara.hutool.core.convert.impl;
|
||||
|
||||
import org.dromara.hutool.core.convert.AbstractConverter;
|
||||
import org.dromara.hutool.core.convert.ConvertException;
|
||||
import org.dromara.hutool.core.convert.MatcherConverter;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* 强转转换器
|
||||
*
|
||||
* @author Looly
|
||||
* @param <T> 强制转换到的类型
|
||||
* @since 4.0.2
|
||||
*/
|
||||
public class CastConverter<T> extends AbstractConverter {
|
||||
public class CastConverter implements MatcherConverter, Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 单例
|
||||
*/
|
||||
public static final CastConverter INSTANCE = new CastConverter();
|
||||
|
||||
@Override
|
||||
protected T convertInternal(final Class<?> targetClass, final Object value) {
|
||||
// 由于在AbstractConverter中已经有类型判断并强制转换,因此当在上一步强制转换失败时直接抛出异常
|
||||
throw new ConvertException("Can not cast value to [{}]", targetClass);
|
||||
public boolean match(final Type targetType, final Class<?> rawType, final Object value) {
|
||||
return rawType.isInstance(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convert(final Type targetType, final Object value) throws ConvertException{
|
||||
// 此处无需逻辑,目标对象类型是value的父类或接口,直接返回匹配即可
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
@@ -29,6 +29,11 @@ import org.dromara.hutool.core.text.StrUtil;
|
||||
public class CharacterConverter extends AbstractConverter {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 单例
|
||||
*/
|
||||
public static final CharacterConverter INSTANCE = new CharacterConverter();
|
||||
|
||||
@Override
|
||||
protected Character convertInternal(final Class<?> targetClass, final Object value) {
|
||||
if (value instanceof Boolean) {
|
||||
|
@@ -18,6 +18,9 @@ package org.dromara.hutool.core.convert.impl;
|
||||
|
||||
import org.dromara.hutool.core.convert.AbstractConverter;
|
||||
import org.dromara.hutool.core.classloader.ClassLoaderUtil;
|
||||
import org.dromara.hutool.core.convert.MatcherConverter;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* 类转换器<br>
|
||||
@@ -25,7 +28,7 @@ import org.dromara.hutool.core.classloader.ClassLoaderUtil;
|
||||
*
|
||||
* @author Looly
|
||||
*/
|
||||
public class ClassConverter extends AbstractConverter {
|
||||
public class ClassConverter extends AbstractConverter implements MatcherConverter {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
@@ -52,6 +55,11 @@ public class ClassConverter extends AbstractConverter {
|
||||
this.isInitialized = isInitialized;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean match(final Type targetType, final Class<?> rawType, final Object value) {
|
||||
return "java.lang.Class".equals(rawType.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> convertInternal(final Class<?> targetClass, final Object value) {
|
||||
return ClassLoaderUtil.loadClass(convertToStr(value), isInitialized);
|
||||
|
@@ -17,10 +17,11 @@
|
||||
package org.dromara.hutool.core.convert.impl;
|
||||
|
||||
import org.dromara.hutool.core.collection.CollUtil;
|
||||
import org.dromara.hutool.core.convert.Converter;
|
||||
import org.dromara.hutool.core.convert.MatcherConverter;
|
||||
import org.dromara.hutool.core.reflect.TypeReference;
|
||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Collection;
|
||||
|
||||
@@ -30,13 +31,19 @@ import java.util.Collection;
|
||||
* @author Looly
|
||||
* @since 3.0.8
|
||||
*/
|
||||
public class CollectionConverter implements Converter {
|
||||
public class CollectionConverter implements MatcherConverter, Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 单例实体
|
||||
*/
|
||||
public static CollectionConverter INSTANCE = new CollectionConverter();
|
||||
|
||||
@Override
|
||||
public boolean match(final Type targetType, final Class<?> rawType, final Object value) {
|
||||
return Collection.class.isAssignableFrom(rawType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<?> convert(Type targetType, final Object value) {
|
||||
if (targetType instanceof TypeReference) {
|
||||
|
@@ -18,11 +18,13 @@ package org.dromara.hutool.core.convert.impl;
|
||||
|
||||
import org.dromara.hutool.core.convert.AbstractConverter;
|
||||
import org.dromara.hutool.core.convert.ConvertException;
|
||||
import org.dromara.hutool.core.convert.MatcherConverter;
|
||||
import org.dromara.hutool.core.date.DateTime;
|
||||
import org.dromara.hutool.core.date.DateUtil;
|
||||
import org.dromara.hutool.core.date.SqlDateUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
@@ -32,7 +34,7 @@ import java.util.Date;
|
||||
*
|
||||
* @author Looly
|
||||
*/
|
||||
public class DateConverter extends AbstractConverter {
|
||||
public class DateConverter extends AbstractConverter implements MatcherConverter {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
@@ -79,6 +81,11 @@ public class DateConverter extends AbstractConverter {
|
||||
this.format = format;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean match(final Type targetType, final Class<?> rawType, final Object value) {
|
||||
return Date.class.isAssignableFrom(rawType);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected java.util.Date convertInternal(final Class<?> targetClass, final Object value) {
|
||||
if (value == null || (value instanceof CharSequence && StrUtil.isBlank(value.toString()))) {
|
||||
|
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Hutool Team and hutool.cn
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.core.convert.impl;
|
||||
|
||||
import org.dromara.hutool.core.convert.AbstractConverter;
|
||||
import org.dromara.hutool.core.convert.MatcherConverter;
|
||||
import org.dromara.hutool.core.reflect.ConstructorUtil;
|
||||
import org.dromara.hutool.core.util.ObjUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* 空值或空对象转换器,转换结果为目标类型对象的实例化对象
|
||||
*
|
||||
* @author Looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class EmptyBeanConverter extends AbstractConverter implements MatcherConverter, Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 单例
|
||||
*/
|
||||
public static final EmptyBeanConverter INSTANCE = new EmptyBeanConverter();
|
||||
|
||||
@Override
|
||||
public boolean match(final Type targetType, final Class<?> rawType, final Object value) {
|
||||
return ObjUtil.isEmpty(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object convertInternal(final Class<?> targetClass, final Object value) {
|
||||
// issue#3649 空值转空对象,则直接实例化
|
||||
return ConstructorUtil.newInstanceIfPossible(targetClass);
|
||||
}
|
||||
}
|
@@ -19,15 +19,16 @@ package org.dromara.hutool.core.convert.impl;
|
||||
import org.dromara.hutool.core.bean.BeanUtil;
|
||||
import org.dromara.hutool.core.convert.CompositeConverter;
|
||||
import org.dromara.hutool.core.convert.ConvertException;
|
||||
import org.dromara.hutool.core.convert.Converter;
|
||||
import org.dromara.hutool.core.convert.MatcherConverter;
|
||||
import org.dromara.hutool.core.lang.tuple.Pair;
|
||||
import org.dromara.hutool.core.map.MapUtil;
|
||||
import org.dromara.hutool.core.reflect.ConstructorUtil;
|
||||
import org.dromara.hutool.core.reflect.TypeReference;
|
||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.core.text.CharUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -42,13 +43,19 @@ import java.util.Map;
|
||||
*
|
||||
* @author looly
|
||||
*/
|
||||
public class EntryConverter implements Converter {
|
||||
public class EntryConverter implements MatcherConverter, Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 单例
|
||||
*/
|
||||
public static final EntryConverter INSTANCE = new EntryConverter();
|
||||
|
||||
@Override
|
||||
public boolean match(final Type targetType, final Class<?> rawType, final Object value) {
|
||||
return Map.Entry.class.isAssignableFrom(rawType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convert(Type targetType, final Object value) throws ConvertException {
|
||||
if (targetType instanceof TypeReference) {
|
||||
|
@@ -18,6 +18,7 @@ package org.dromara.hutool.core.convert.impl;
|
||||
|
||||
import org.dromara.hutool.core.convert.AbstractConverter;
|
||||
import org.dromara.hutool.core.convert.ConvertException;
|
||||
import org.dromara.hutool.core.convert.MatcherConverter;
|
||||
import org.dromara.hutool.core.lang.EnumItem;
|
||||
import org.dromara.hutool.core.map.MapUtil;
|
||||
import org.dromara.hutool.core.map.reference.WeakConcurrentMap;
|
||||
@@ -27,6 +28,7 @@ import org.dromara.hutool.core.reflect.method.MethodUtil;
|
||||
import org.dromara.hutool.core.util.EnumUtil;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -38,7 +40,7 @@ import java.util.stream.Collectors;
|
||||
* @since 4.0.2
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public class EnumConverter extends AbstractConverter {
|
||||
public class EnumConverter extends AbstractConverter implements MatcherConverter {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
@@ -48,6 +50,11 @@ public class EnumConverter extends AbstractConverter {
|
||||
|
||||
private static final WeakConcurrentMap<Class<?>, Map<Class<?>, Method>> VALUE_OF_METHOD_CACHE = new WeakConcurrentMap<>();
|
||||
|
||||
@Override
|
||||
public boolean match(final Type targetType, final Class<?> rawType, final Object value) {
|
||||
return rawType.isEnum();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object convertInternal(final Class<?> targetClass, final Object value) {
|
||||
Enum enumValue = tryConvertEnum(value, targetClass);
|
||||
|
@@ -22,6 +22,7 @@ import org.dromara.hutool.core.bean.copier.provider.BeanValueProvider;
|
||||
import org.dromara.hutool.core.bean.copier.provider.MapValueProvider;
|
||||
import org.dromara.hutool.core.convert.ConvertException;
|
||||
import org.dromara.hutool.core.convert.Converter;
|
||||
import org.dromara.hutool.core.convert.MatcherConverter;
|
||||
import org.dromara.hutool.core.lang.Assert;
|
||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||
import org.dromara.hutool.core.reflect.kotlin.KClassUtil;
|
||||
@@ -40,7 +41,7 @@ import java.util.Map;
|
||||
*
|
||||
* @author Looly
|
||||
*/
|
||||
public class KBeanConverter implements Converter, Serializable {
|
||||
public class KBeanConverter implements MatcherConverter, Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
@@ -48,6 +49,11 @@ public class KBeanConverter implements Converter, Serializable {
|
||||
*/
|
||||
public static KBeanConverter INSTANCE = new KBeanConverter();
|
||||
|
||||
@Override
|
||||
public boolean match(final Type targetType, final Class<?> rawType, final Object value) {
|
||||
return KClassUtil.isKotlinClass(rawType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convert(final Type targetType, final Object value) throws ConvertException {
|
||||
Assert.notNull(targetType);
|
||||
|
@@ -19,7 +19,7 @@ package org.dromara.hutool.core.convert.impl;
|
||||
import org.dromara.hutool.core.bean.BeanUtil;
|
||||
import org.dromara.hutool.core.convert.CompositeConverter;
|
||||
import org.dromara.hutool.core.convert.ConvertException;
|
||||
import org.dromara.hutool.core.convert.Converter;
|
||||
import org.dromara.hutool.core.convert.MatcherConverter;
|
||||
import org.dromara.hutool.core.map.MapUtil;
|
||||
import org.dromara.hutool.core.reflect.TypeReference;
|
||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||
@@ -40,7 +40,7 @@ import java.util.Objects;
|
||||
* @author Looly
|
||||
* @since 3.0.8
|
||||
*/
|
||||
public class MapConverter implements Converter, Serializable {
|
||||
public class MapConverter implements MatcherConverter, Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
@@ -48,6 +48,11 @@ public class MapConverter implements Converter, Serializable {
|
||||
*/
|
||||
public static MapConverter INSTANCE = new MapConverter();
|
||||
|
||||
@Override
|
||||
public boolean match(final Type targetType, final Class<?> rawType, final Object value) {
|
||||
return Map.class.isAssignableFrom(rawType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convert(Type targetType, final Object value) throws ConvertException {
|
||||
if (targetType instanceof TypeReference) {
|
||||
|
@@ -18,12 +18,14 @@ package org.dromara.hutool.core.convert.impl;
|
||||
|
||||
import org.dromara.hutool.core.convert.AbstractConverter;
|
||||
import org.dromara.hutool.core.convert.ConvertException;
|
||||
import org.dromara.hutool.core.convert.MatcherConverter;
|
||||
import org.dromara.hutool.core.date.DateUtil;
|
||||
import org.dromara.hutool.core.math.NumberUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.core.util.BooleanUtil;
|
||||
import org.dromara.hutool.core.util.ByteUtil;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
@@ -53,7 +55,7 @@ import java.util.function.Function;
|
||||
*
|
||||
* @author Looly
|
||||
*/
|
||||
public class NumberConverter extends AbstractConverter {
|
||||
public class NumberConverter extends AbstractConverter implements MatcherConverter {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
@@ -61,6 +63,11 @@ public class NumberConverter extends AbstractConverter {
|
||||
*/
|
||||
public static final NumberConverter INSTANCE = new NumberConverter();
|
||||
|
||||
@Override
|
||||
public boolean match(final Type targetType, final Class<?> rawType, final Object value) {
|
||||
return Number.class.isAssignableFrom(rawType);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected Number convertInternal(final Class<?> targetClass, final Object value) {
|
||||
|
@@ -17,12 +17,11 @@
|
||||
package org.dromara.hutool.core.convert.impl;
|
||||
|
||||
import org.dromara.hutool.core.convert.AbstractConverter;
|
||||
import org.dromara.hutool.core.convert.ConvertUtil;
|
||||
import org.dromara.hutool.core.convert.ConvertException;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.core.util.ObjUtil;
|
||||
import org.dromara.hutool.core.convert.MatcherConverter;
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* 原始类型转换器<br>
|
||||
@@ -40,7 +39,7 @@ import java.util.function.Function;
|
||||
*
|
||||
* @author Looly
|
||||
*/
|
||||
public class PrimitiveConverter extends AbstractConverter {
|
||||
public class PrimitiveConverter extends AbstractConverter implements MatcherConverter, Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
@@ -48,51 +47,38 @@ public class PrimitiveConverter extends AbstractConverter {
|
||||
*/
|
||||
public static final PrimitiveConverter INSTANCE = new PrimitiveConverter();
|
||||
|
||||
/**
|
||||
* 构造<br>
|
||||
*
|
||||
* @throws IllegalArgumentException 传入的转换类型非原始类型时抛出
|
||||
*/
|
||||
public PrimitiveConverter() {
|
||||
@Override
|
||||
public boolean match(final Type targetType, final Class<?> rawType, final Object value) {
|
||||
return rawType.isPrimitive();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object convertInternal(final Class<?> targetClass, final Object value) {
|
||||
return PrimitiveConverter.convert(value, targetClass, this::convertToStr);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String convertToStr(final Object value) {
|
||||
return StrUtil.trim(super.convertToStr(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* 将指定值转换为原始类型的值
|
||||
* @param value 值
|
||||
* @param primitiveClass 原始类型
|
||||
* @param toStringFunc 当无法直接转换时,转为字符串后再转换的函数
|
||||
* @return 转换结果
|
||||
* @since 5.5.0
|
||||
*/
|
||||
protected static Object convert(final Object value, final Class<?> primitiveClass, final Function<Object, String> toStringFunc) {
|
||||
protected Object convertInternal(final Class<?> primitiveClass, final Object value) {
|
||||
final Object result;
|
||||
if (byte.class == primitiveClass) {
|
||||
return ObjUtil.defaultIfNull(NumberConverter.convert(value, Byte.class, toStringFunc), 0);
|
||||
result = NumberConverter.INSTANCE.convert(Byte.class, value);
|
||||
} else if (short.class == primitiveClass) {
|
||||
return ObjUtil.defaultIfNull(NumberConverter.convert(value, Short.class, toStringFunc), 0);
|
||||
result = NumberConverter.INSTANCE.convert(Short.class, value);
|
||||
} else if (int.class == primitiveClass) {
|
||||
return ObjUtil.defaultIfNull(NumberConverter.convert(value, Integer.class, toStringFunc), 0);
|
||||
result = NumberConverter.INSTANCE.convert(Integer.class, value);
|
||||
} else if (long.class == primitiveClass) {
|
||||
return ObjUtil.defaultIfNull(NumberConverter.convert(value, Long.class, toStringFunc), 0);
|
||||
result = NumberConverter.INSTANCE.convert(Long.class, value);
|
||||
} else if (float.class == primitiveClass) {
|
||||
return ObjUtil.defaultIfNull(NumberConverter.convert(value, Float.class, toStringFunc), 0);
|
||||
result = NumberConverter.INSTANCE.convert(Float.class, value);
|
||||
} else if (double.class == primitiveClass) {
|
||||
return ObjUtil.defaultIfNull(NumberConverter.convert(value, Double.class, toStringFunc), 0);
|
||||
result = NumberConverter.INSTANCE.convert(Double.class, value);
|
||||
} else if (char.class == primitiveClass) {
|
||||
return ConvertUtil.convert(Character.class, value);
|
||||
result = CharacterConverter.INSTANCE.convert(Character.class, value);
|
||||
} else if (boolean.class == primitiveClass) {
|
||||
return ConvertUtil.convert(Boolean.class, value);
|
||||
result = BooleanConverter.INSTANCE.convert(Boolean.class, value);
|
||||
} else{
|
||||
throw new ConvertException("Unsupported target type: {}", primitiveClass);
|
||||
}
|
||||
|
||||
throw new ConvertException("Unsupported target type: {}", primitiveClass);
|
||||
if(null == result){
|
||||
throw new ConvertException("Can not convert {} to {}", value, primitiveClass);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@@ -23,7 +23,9 @@ import org.dromara.hutool.core.bean.copier.provider.BeanValueProvider;
|
||||
import org.dromara.hutool.core.bean.copier.provider.MapValueProvider;
|
||||
import org.dromara.hutool.core.convert.AbstractConverter;
|
||||
import org.dromara.hutool.core.convert.ConvertException;
|
||||
import org.dromara.hutool.core.convert.MatcherConverter;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -34,7 +36,7 @@ import java.util.Map;
|
||||
* ValueProvider =》 Record
|
||||
* </pre>
|
||||
*/
|
||||
public class RecordConverter extends AbstractConverter {
|
||||
public class RecordConverter extends AbstractConverter implements MatcherConverter {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
@@ -42,6 +44,11 @@ public class RecordConverter extends AbstractConverter {
|
||||
*/
|
||||
public static RecordConverter INSTANCE = new RecordConverter();
|
||||
|
||||
@Override
|
||||
public boolean match(final Type targetType, final Class<?> rawType, final Object value) {
|
||||
return RecordUtil.isRecord(rawType);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected Object convertInternal(final Class<?> targetClass, final Object value) {
|
||||
|
@@ -23,7 +23,7 @@ public class SemaphoreRateLimiterTest {
|
||||
final boolean b1 = rateLimiter.tryAcquire(1);
|
||||
Assertions.assertFalse(b1);
|
||||
|
||||
ThreadUtil.sleep(310);
|
||||
ThreadUtil.sleep(400);
|
||||
|
||||
// 填充新的许可
|
||||
final boolean b2 = rateLimiter.tryAcquire(5);
|
||||
|
@@ -18,13 +18,13 @@ package org.dromara.hutool.json.convert;
|
||||
|
||||
import org.dromara.hutool.core.array.ArrayUtil;
|
||||
import org.dromara.hutool.core.bean.BeanUtil;
|
||||
import org.dromara.hutool.core.bean.RecordUtil;
|
||||
import org.dromara.hutool.core.bean.copier.BeanCopier;
|
||||
import org.dromara.hutool.core.convert.ConvertUtil;
|
||||
import org.dromara.hutool.core.convert.ConvertException;
|
||||
import org.dromara.hutool.core.convert.ConvertUtil;
|
||||
import org.dromara.hutool.core.convert.Converter;
|
||||
import org.dromara.hutool.core.convert.RegisterConverter;
|
||||
import org.dromara.hutool.core.convert.impl.*;
|
||||
import org.dromara.hutool.core.convert.impl.DateConverter;
|
||||
import org.dromara.hutool.core.convert.impl.TemporalAccessorConverter;
|
||||
import org.dromara.hutool.core.lang.Opt;
|
||||
import org.dromara.hutool.core.map.MapWrapper;
|
||||
import org.dromara.hutool.core.reflect.ConstructorUtil;
|
||||
@@ -40,7 +40,9 @@ import org.dromara.hutool.json.serialize.JSONStringer;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Type;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.*;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* JSON转换器,实现Object对象转换为{@link JSON},支持的对象:
|
||||
@@ -232,7 +234,7 @@ public class JSONConverter implements Converter, Serializable {
|
||||
//throw new JSONException("Can not get class from type: {}", targetType);
|
||||
}
|
||||
// 特殊类型转换,包括Collection、Map、强转、Array等
|
||||
final T result = toSpecial(targetType, rawType, json);
|
||||
final T result = (T) JSONSpecialConverter.getInstance().convert(targetType, rawType, json);
|
||||
if (null != result) {
|
||||
return result;
|
||||
}
|
||||
@@ -265,74 +267,6 @@ public class JSONConverter implements Converter, Serializable {
|
||||
json.getClass().getName(), json, targetType.getTypeName());
|
||||
}
|
||||
|
||||
/**
|
||||
* 特殊类型转换<br>
|
||||
* 包括:
|
||||
*
|
||||
* <pre>
|
||||
* Collection
|
||||
* Map
|
||||
* Map.Entry
|
||||
* 强转(无需转换)
|
||||
* 数组
|
||||
* </pre>
|
||||
*
|
||||
* @param <T> 转换的目标类型(转换器转换到的类型)
|
||||
* @param type 类型
|
||||
* @param value 值
|
||||
* @return 转换后的值
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T toSpecial(final Type type, final Class<T> rowType, final JSON value) {
|
||||
if (null == rowType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 日期、java.sql中的日期以及自定义日期统一处理
|
||||
if (Date.class.isAssignableFrom(rowType)) {
|
||||
return (T) DateConverter.INSTANCE.convert(type, value);
|
||||
}
|
||||
|
||||
// 集合转换(含有泛型参数,不可以默认强转)
|
||||
if (Collection.class.isAssignableFrom(rowType)) {
|
||||
return (T) CollectionConverter.INSTANCE.convert(type, value);
|
||||
}
|
||||
|
||||
// Map类型(含有泛型参数,不可以默认强转)
|
||||
if (Map.class.isAssignableFrom(rowType)) {
|
||||
return (T) MapConverter.INSTANCE.convert(type, value);
|
||||
}
|
||||
|
||||
// issue#I6SZYB Entry类(含有泛型参数,不可以默认强转)
|
||||
if (Map.Entry.class.isAssignableFrom(rowType)) {
|
||||
return (T) EntryConverter.INSTANCE.convert(type, value);
|
||||
}
|
||||
|
||||
// 默认强转
|
||||
if (rowType.isInstance(value)) {
|
||||
return (T) value;
|
||||
}
|
||||
|
||||
// 数组转换
|
||||
if (rowType.isArray()) {
|
||||
return (T) ArrayConverter.INSTANCE.convert(type, value);
|
||||
}
|
||||
|
||||
// Record
|
||||
if (RecordUtil.isRecord(rowType)) {
|
||||
return (T) RecordConverter.INSTANCE.convert(type, value);
|
||||
}
|
||||
|
||||
// 空值转空Bean
|
||||
if (ObjUtil.isEmpty(value)) {
|
||||
// issue#3649 空值转空对象,则直接实例化
|
||||
return ConstructorUtil.newInstanceIfPossible(rowType);
|
||||
}
|
||||
|
||||
// 表示非需要特殊转换的对象
|
||||
return null;
|
||||
}
|
||||
|
||||
private Object toDateWithFormat(final Class<?> targetClass, final Object value) {
|
||||
// 日期转换,支持自定义日期格式
|
||||
final String format = config.getDateFormat();
|
||||
|
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Hutool Team and hutool.cn
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.json.convert;
|
||||
|
||||
import org.dromara.hutool.core.convert.ConvertException;
|
||||
import org.dromara.hutool.core.convert.Converter;
|
||||
import org.dromara.hutool.core.convert.MatcherConverter;
|
||||
import org.dromara.hutool.core.convert.impl.*;
|
||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||
import org.dromara.hutool.core.stream.StreamUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 特殊类型转换器,如果不符合特殊类型,则返回{@code null}继续其它转换规则<br>
|
||||
* 对于特殊对象(如集合、Map、Enum、数组)等的转换器,实现转换<br>
|
||||
* 注意:此类中的转换器查找是通过遍历方式
|
||||
*
|
||||
* @author Looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class JSONSpecialConverter implements Converter, Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例 没有绑定关系,而且只有被调用到才会装载,从而实现了延迟加载
|
||||
*/
|
||||
private static class SingletonHolder {
|
||||
/**
|
||||
* 静态初始化器,由JVM来保证线程安全
|
||||
*/
|
||||
private static final JSONSpecialConverter INSTANCE = new JSONSpecialConverter();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得单例的 CustomConverter
|
||||
*
|
||||
* @return CustomConverter
|
||||
*/
|
||||
public static JSONSpecialConverter getInstance() {
|
||||
return JSONSpecialConverter.SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 类型转换器集合<br>
|
||||
* 此集合初始化后不再加入新值,因此单例使用线程安全
|
||||
*/
|
||||
private final Set<MatcherConverter> converterSet;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*/
|
||||
private JSONSpecialConverter() {
|
||||
final Set<MatcherConverter> converterSet = new LinkedHashSet<>(64);
|
||||
|
||||
// 集合转换(含有泛型参数,不可以默认强转)
|
||||
converterSet.add(CollectionConverter.INSTANCE);
|
||||
// Map类型(含有泛型参数,不可以默认强转)
|
||||
converterSet.add(MapConverter.INSTANCE);
|
||||
// issue#I6SZYB Entry类(含有泛型参数,不可以默认强转)
|
||||
converterSet.add(EntryConverter.INSTANCE);
|
||||
// 默认强转
|
||||
converterSet.add(CastConverter.INSTANCE);
|
||||
// 日期、java.sql中的日期以及自定义日期统一处理
|
||||
converterSet.add(DateConverter.INSTANCE);
|
||||
// 原始类型转换
|
||||
converterSet.add(PrimitiveConverter.INSTANCE);
|
||||
// 数字类型转换
|
||||
converterSet.add(NumberConverter.INSTANCE);
|
||||
// 枚举转换
|
||||
converterSet.add(EnumConverter.INSTANCE);
|
||||
// 数组转换
|
||||
converterSet.add(ArrayConverter.INSTANCE);
|
||||
// Record
|
||||
converterSet.add(RecordConverter.INSTANCE);
|
||||
// issue#I7FQ29 Class
|
||||
converterSet.add(ClassConverter.INSTANCE);
|
||||
// // 空值转空Bean
|
||||
converterSet.add(EmptyBeanConverter.INSTANCE);
|
||||
|
||||
this.converterSet = converterSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convert(final Type targetType, final Object value) throws ConvertException {
|
||||
return convert(targetType, TypeUtil.getClass(targetType), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换值
|
||||
*
|
||||
* @param targetType 目标类型
|
||||
* @param rawType 目标原始类型(即目标的Class)
|
||||
* @param value 被转换的值
|
||||
* @return 转换后的值,如果无转换器,返回{@code null}
|
||||
* @throws ConvertException 转换异常,即找到了对应的转换器,但是转换失败
|
||||
*/
|
||||
public Object convert(final Type targetType, final Class<?> rawType, final Object value) throws ConvertException {
|
||||
final Converter converter = getConverter(targetType, rawType, value);
|
||||
return null == converter ? null : converter.convert(targetType, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得匹配的转换器
|
||||
*
|
||||
* @param type 类型
|
||||
* @param rawType 目标类型的Class
|
||||
* @param value 被转换的值
|
||||
* @return 转换器
|
||||
*/
|
||||
public Converter getConverter(final Type type, final Class<?> rawType, final Object value) {
|
||||
return getConverterFromSet(this.converterSet, type, rawType, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从指定集合中查找满足条件的转换器
|
||||
*
|
||||
* @param type 类型
|
||||
* @return 转换器
|
||||
*/
|
||||
private static Converter getConverterFromSet(final Set<? extends MatcherConverter> converterSet, final Type type, final Class<?> rawType, final Object value) {
|
||||
return StreamUtil.of(converterSet).filter((predicate) -> predicate.match(type, rawType, value)).findFirst().orElse(null);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user