mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
fix code
This commit is contained in:
parent
47fe46c495
commit
ee13716d42
@ -30,6 +30,7 @@ import org.dromara.hutool.core.comparator.PinyinComparator;
|
|||||||
import org.dromara.hutool.core.comparator.PropertyComparator;
|
import org.dromara.hutool.core.comparator.PropertyComparator;
|
||||||
import org.dromara.hutool.core.convert.CompositeConverter;
|
import org.dromara.hutool.core.convert.CompositeConverter;
|
||||||
import org.dromara.hutool.core.convert.ConvertUtil;
|
import org.dromara.hutool.core.convert.ConvertUtil;
|
||||||
|
import org.dromara.hutool.core.convert.Converter;
|
||||||
import org.dromara.hutool.core.exception.ExceptionUtil;
|
import org.dromara.hutool.core.exception.ExceptionUtil;
|
||||||
import org.dromara.hutool.core.func.SerBiConsumer;
|
import org.dromara.hutool.core.func.SerBiConsumer;
|
||||||
import org.dromara.hutool.core.func.SerConsumer3;
|
import org.dromara.hutool.core.func.SerConsumer3;
|
||||||
@ -401,7 +402,7 @@ public class CollUtil {
|
|||||||
* @return 单差集
|
* @return 单差集
|
||||||
*/
|
*/
|
||||||
public static <T> Collection<T> subtract(final Collection<T> coll1, final Collection<T> coll2) {
|
public static <T> Collection<T> subtract(final Collection<T> coll1, final Collection<T> coll2) {
|
||||||
if(isEmpty(coll1) || isEmpty(coll2)){
|
if (isEmpty(coll1) || isEmpty(coll2)) {
|
||||||
return coll1;
|
return coll1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -530,7 +531,7 @@ public class CollUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set直接判定
|
// Set直接判定
|
||||||
if(coll1 instanceof Set){
|
if (coll1 instanceof Set) {
|
||||||
return coll1.containsAll(coll2);
|
return coll1.containsAll(coll2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1571,8 +1572,24 @@ public class CollUtil {
|
|||||||
* @param elementType 元素类型,为空时,使用Object类型来接纳所有类型
|
* @param elementType 元素类型,为空时,使用Object类型来接纳所有类型
|
||||||
* @return 被加入集合
|
* @return 被加入集合
|
||||||
*/
|
*/
|
||||||
|
public static <T> Collection<T> addAll(final Collection<T> collection, final Object value, final Type elementType) {
|
||||||
|
return addAll(collection, value, elementType, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将指定对象全部加入到集合中<br>
|
||||||
|
* 提供的对象如果为集合类型,会自动转换为目标元素类型<br>
|
||||||
|
* 如果为String,支持类似于[1,2,3,4] 或者 1,2,3,4 这种格式
|
||||||
|
*
|
||||||
|
* @param <T> 元素类型
|
||||||
|
* @param collection 被加入的集合
|
||||||
|
* @param value 对象,可能为Iterator、Iterable、Enumeration、Array,或者与集合元素类型一致
|
||||||
|
* @param elementType 元素类型,为空时,使用Object类型来接纳所有类型
|
||||||
|
* @param converter 自定义元素类型转换器,{@code null}表示使用默认转换器
|
||||||
|
* @return 被加入集合
|
||||||
|
*/
|
||||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||||
public static <T> Collection<T> addAll(final Collection<T> collection, final Object value, Type elementType) {
|
public static <T> Collection<T> addAll(final Collection<T> collection, final Object value, Type elementType, final Converter converter) {
|
||||||
if (null == collection || null == value) {
|
if (null == collection || null == value) {
|
||||||
return collection;
|
return collection;
|
||||||
}
|
}
|
||||||
@ -1595,7 +1612,7 @@ public class CollUtil {
|
|||||||
iter = IterUtil.getIter(value);
|
iter = IterUtil.getIter(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
final CompositeConverter convert = CompositeConverter.getInstance();
|
final Converter convert = ObjUtil.defaultIfNull(converter, CompositeConverter::getInstance);
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
collection.add((T) convert.convert(elementType, iter.next()));
|
collection.add((T) convert.convert(elementType, iter.next()));
|
||||||
}
|
}
|
||||||
@ -2316,12 +2333,12 @@ public class CollUtil {
|
|||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @param subCollection 第一个Iterable对象,即子集合。
|
* @param subCollection 第一个Iterable对象,即子集合。
|
||||||
* @param collection 第二个Iterable对象,可以为任何实现了Iterable接口的集合。
|
* @param collection 第二个Iterable对象,可以为任何实现了Iterable接口的集合。
|
||||||
* @return 如果subCollection是collection的子集合,则返回true;否则返回false。
|
* @return 如果subCollection是collection的子集合,则返回true;否则返回false。
|
||||||
* @since 6.0.0
|
* @since 6.0.0
|
||||||
*/
|
*/
|
||||||
public static boolean isSub(final Collection<?> subCollection, final Collection<?> collection) {
|
public static boolean isSub(final Collection<?> subCollection, final Collection<?> collection) {
|
||||||
if(size(subCollection) > size(collection)){
|
if (size(subCollection) > size(collection)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return IterUtil.isSub(subCollection, collection);
|
return IterUtil.isSub(subCollection, collection);
|
||||||
@ -2354,13 +2371,13 @@ public class CollUtil {
|
|||||||
* <li>如果不忽略顺序,两个{@link Iterable}所有具有相同下标的元素皆满足{@link Objects#equals(Object, Object)};</li>
|
* <li>如果不忽略顺序,两个{@link Iterable}所有具有相同下标的元素皆满足{@link Objects#equals(Object, Object)};</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @param coll1 集合1
|
* @param coll1 集合1
|
||||||
* @param coll2 集合2
|
* @param coll2 集合2
|
||||||
* @param ignoreOrder 是否忽略顺序
|
* @param ignoreOrder 是否忽略顺序
|
||||||
* @return 是否相同
|
* @return 是否相同
|
||||||
*/
|
*/
|
||||||
public static boolean equals(final Collection<?> coll1, final Collection<?> coll2, final boolean ignoreOrder) {
|
public static boolean equals(final Collection<?> coll1, final Collection<?> coll2, final boolean ignoreOrder) {
|
||||||
if(size(coll1) != size(coll2)){
|
if (size(coll1) != size(coll2)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ import org.dromara.hutool.core.reflect.TypeReference;
|
|||||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||||
import org.dromara.hutool.core.util.ObjUtil;
|
import org.dromara.hutool.core.util.ObjUtil;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@ -36,7 +37,7 @@ import java.util.Optional;
|
|||||||
*
|
*
|
||||||
* @author Looly
|
* @author Looly
|
||||||
*/
|
*/
|
||||||
public class CompositeConverter extends RegisterConverter {
|
public class CompositeConverter implements Converter, Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -46,7 +47,12 @@ public class CompositeConverter extends RegisterConverter {
|
|||||||
/**
|
/**
|
||||||
* 静态初始化器,由JVM来保证线程安全
|
* 静态初始化器,由JVM来保证线程安全
|
||||||
*/
|
*/
|
||||||
private static final CompositeConverter INSTANCE = new CompositeConverter();
|
private static final CompositeConverter INSTANCE;
|
||||||
|
static {
|
||||||
|
INSTANCE = new CompositeConverter();
|
||||||
|
INSTANCE.registerConverter = new RegisterConverter(INSTANCE);
|
||||||
|
INSTANCE.specialConverter = new SpecialConverter(INSTANCE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -58,11 +64,38 @@ public class CompositeConverter extends RegisterConverter {
|
|||||||
return SingletonHolder.INSTANCE;
|
return SingletonHolder.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private RegisterConverter registerConverter;
|
||||||
|
private SpecialConverter specialConverter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造
|
* 构造
|
||||||
*/
|
*/
|
||||||
public CompositeConverter() {
|
private CompositeConverter() {
|
||||||
super();
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登记自定义转换器,符合{@link MatcherConverter#match(Type, Class, Object)}则使用其转换器<br>
|
||||||
|
* 注意:如果单例使用,此方法会影响全局
|
||||||
|
*
|
||||||
|
* @param converter 转换器
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public CompositeConverter register(final MatcherConverter converter) {
|
||||||
|
registerConverter.register(converter);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登记自定义转换器,登记的目标类型必须一致<br>
|
||||||
|
* 注意:如果单例使用,此方法会影响全局
|
||||||
|
*
|
||||||
|
* @param type 转换的目标类型
|
||||||
|
* @param converter 转换器
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public CompositeConverter register(final Type type, final Converter converter) {
|
||||||
|
registerConverter.register(type, converter);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -142,7 +175,7 @@ public class CompositeConverter extends RegisterConverter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 标准转换器
|
// 标准转换器
|
||||||
final Converter converter = getConverter(type, value, isCustomFirst);
|
final Converter converter = registerConverter.getConverter(type, value, isCustomFirst);
|
||||||
if (null != converter) {
|
if (null != converter) {
|
||||||
return converter.convert(type, value, defaultValue);
|
return converter.convert(type, value, defaultValue);
|
||||||
}
|
}
|
||||||
@ -157,7 +190,7 @@ public class CompositeConverter extends RegisterConverter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 特殊类型转换,包括Collection、Map、强转、Array等
|
// 特殊类型转换,包括Collection、Map、强转、Array等
|
||||||
final T result = (T) SpecialConverter.getInstance().convert(type, rawType, value);
|
final T result = (T) specialConverter.convert(type, rawType, value);
|
||||||
if (null != result) {
|
if (null != result) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* 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.lang.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 带根的转换器<br>
|
||||||
|
* 在嵌套对象转换中,如果涉及子对象的转换,使用根转换器转换
|
||||||
|
*
|
||||||
|
* @author Looly
|
||||||
|
* @since 6.0.0
|
||||||
|
*/
|
||||||
|
public abstract class ConverterWithRoot implements Converter {
|
||||||
|
|
||||||
|
protected final Converter rootConverter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param rootConverter 根转换器
|
||||||
|
*/
|
||||||
|
public ConverterWithRoot(final Converter rootConverter) {
|
||||||
|
this.rootConverter = Assert.notNull(rootConverter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取根转换器,用于子转换器转换
|
||||||
|
*
|
||||||
|
* @return 根转换器
|
||||||
|
*/
|
||||||
|
public Converter getRootConverter() {
|
||||||
|
return rootConverter;
|
||||||
|
}
|
||||||
|
}
|
@ -54,28 +54,9 @@ import java.util.concurrent.atomic.AtomicReference;
|
|||||||
* @author looly
|
* @author looly
|
||||||
* @since 6.0.0
|
* @since 6.0.0
|
||||||
*/
|
*/
|
||||||
public class RegisterConverter implements Converter, Serializable {
|
public class RegisterConverter extends ConverterWithRoot implements Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/**
|
|
||||||
* 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例 没有绑定关系,而且只有被调用到才会装载,从而实现了延迟加载
|
|
||||||
*/
|
|
||||||
private static class SingletonHolder {
|
|
||||||
/**
|
|
||||||
* 静态初始化器,由JVM来保证线程安全
|
|
||||||
*/
|
|
||||||
private static final RegisterConverter INSTANCE = new RegisterConverter();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得单例的 RegisterConverter
|
|
||||||
*
|
|
||||||
* @return RegisterConverter
|
|
||||||
*/
|
|
||||||
public static RegisterConverter getInstance() {
|
|
||||||
return RegisterConverter.SingletonHolder.INSTANCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户自定义类型转换器,存储自定义匹配规则的一类对象的转换器
|
* 用户自定义类型转换器,存储自定义匹配规则的一类对象的转换器
|
||||||
*/
|
*/
|
||||||
@ -88,13 +69,16 @@ public class RegisterConverter implements Converter, Serializable {
|
|||||||
/**
|
/**
|
||||||
* 默认类型转换器
|
* 默认类型转换器
|
||||||
*/
|
*/
|
||||||
private Map<Class<?>, Converter> defaultConverterMap;
|
private final Map<Class<?>, Converter> defaultConverterMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造
|
* 构造
|
||||||
|
*
|
||||||
|
* @param rootConverter 根转换器,用于子转换器转换
|
||||||
*/
|
*/
|
||||||
public RegisterConverter() {
|
public RegisterConverter(final Converter rootConverter) {
|
||||||
registerDefault();
|
super(rootConverter);
|
||||||
|
this.defaultConverterMap = initDefault(rootConverter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -121,7 +105,7 @@ public class RegisterConverter implements Converter, Serializable {
|
|||||||
Converter converter;
|
Converter converter;
|
||||||
if (isCustomFirst) {
|
if (isCustomFirst) {
|
||||||
converter = this.getCustomConverter(type, value);
|
converter = this.getCustomConverter(type, value);
|
||||||
if(null == converter){
|
if (null == converter) {
|
||||||
converter = this.getCustomConverter(type);
|
converter = this.getCustomConverter(type);
|
||||||
}
|
}
|
||||||
if (null == converter) {
|
if (null == converter) {
|
||||||
@ -132,7 +116,7 @@ public class RegisterConverter implements Converter, Serializable {
|
|||||||
if (null == converter) {
|
if (null == converter) {
|
||||||
converter = this.getCustomConverter(type, value);
|
converter = this.getCustomConverter(type, value);
|
||||||
}
|
}
|
||||||
if(null == converter){
|
if (null == converter) {
|
||||||
converter = this.getCustomConverter(type);
|
converter = this.getCustomConverter(type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -179,7 +163,7 @@ public class RegisterConverter implements Converter, Serializable {
|
|||||||
*
|
*
|
||||||
* @param type 转换的目标类型
|
* @param type 转换的目标类型
|
||||||
* @param converter 转换器
|
* @param converter 转换器
|
||||||
* @return ConverterRegistry
|
* @return this
|
||||||
*/
|
*/
|
||||||
public RegisterConverter register(final Type type, final Converter converter) {
|
public RegisterConverter register(final Type type, final Converter converter) {
|
||||||
if (null == customConverterMap) {
|
if (null == customConverterMap) {
|
||||||
@ -197,7 +181,7 @@ public class RegisterConverter implements Converter, Serializable {
|
|||||||
* 登记自定义转换器,符合{@link MatcherConverter#match(Type, Class, Object)}则使用其转换器
|
* 登记自定义转换器,符合{@link MatcherConverter#match(Type, Class, Object)}则使用其转换器
|
||||||
*
|
*
|
||||||
* @param converter 转换器
|
* @param converter 转换器
|
||||||
* @return ConverterRegistry
|
* @return this
|
||||||
*/
|
*/
|
||||||
public RegisterConverter register(final MatcherConverter converter) {
|
public RegisterConverter register(final MatcherConverter converter) {
|
||||||
if (null == this.converterSet) {
|
if (null == this.converterSet) {
|
||||||
@ -212,65 +196,68 @@ public class RegisterConverter implements Converter, Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注册默认转换器
|
* 初始化默认转换器
|
||||||
|
*
|
||||||
|
* @return 默认转换器
|
||||||
*/
|
*/
|
||||||
private void registerDefault() {
|
private static Map<Class<?>, Converter> initDefault(final Converter rootConverter) {
|
||||||
final Map<Class<?>, Converter> defaultConverterMap = new SafeConcurrentHashMap<>(64);
|
final Map<Class<?>, Converter> converterMap = new SafeConcurrentHashMap<>(64);
|
||||||
|
|
||||||
// 包装类转换器
|
// 包装类转换器
|
||||||
defaultConverterMap.put(Character.class, CharacterConverter.INSTANCE);
|
converterMap.put(Character.class, CharacterConverter.INSTANCE);
|
||||||
defaultConverterMap.put(Boolean.class, BooleanConverter.INSTANCE);
|
converterMap.put(Boolean.class, BooleanConverter.INSTANCE);
|
||||||
defaultConverterMap.put(AtomicBoolean.class, AtomicBooleanConverter.INSTANCE);// since 3.0.8
|
converterMap.put(AtomicBoolean.class, AtomicBooleanConverter.INSTANCE);// since 3.0.8
|
||||||
final StringConverter stringConverter = new StringConverter();
|
final StringConverter stringConverter = new StringConverter();
|
||||||
defaultConverterMap.put(CharSequence.class, stringConverter);
|
converterMap.put(CharSequence.class, stringConverter);
|
||||||
defaultConverterMap.put(String.class, stringConverter);
|
converterMap.put(String.class, stringConverter);
|
||||||
|
|
||||||
// URI and URL
|
// URI and URL
|
||||||
defaultConverterMap.put(URI.class, new URIConverter());
|
converterMap.put(URI.class, new URIConverter());
|
||||||
defaultConverterMap.put(URL.class, new URLConverter());
|
converterMap.put(URL.class, new URLConverter());
|
||||||
|
|
||||||
// 日期时间
|
// 日期时间
|
||||||
defaultConverterMap.put(Calendar.class, new CalendarConverter());
|
converterMap.put(Calendar.class, new CalendarConverter());
|
||||||
defaultConverterMap.put(XMLGregorianCalendar.class, new XMLGregorianCalendarConverter());
|
converterMap.put(XMLGregorianCalendar.class, new XMLGregorianCalendarConverter());
|
||||||
|
|
||||||
// 日期时间 JDK8+(since 5.0.0)
|
// 日期时间 JDK8+(since 5.0.0)
|
||||||
defaultConverterMap.put(TemporalAccessor.class, TemporalAccessorConverter.INSTANCE);
|
converterMap.put(TemporalAccessor.class, TemporalAccessorConverter.INSTANCE);
|
||||||
defaultConverterMap.put(Instant.class, TemporalAccessorConverter.INSTANCE);
|
converterMap.put(Instant.class, TemporalAccessorConverter.INSTANCE);
|
||||||
defaultConverterMap.put(LocalDateTime.class, TemporalAccessorConverter.INSTANCE);
|
converterMap.put(LocalDateTime.class, TemporalAccessorConverter.INSTANCE);
|
||||||
defaultConverterMap.put(LocalDate.class, TemporalAccessorConverter.INSTANCE);
|
converterMap.put(LocalDate.class, TemporalAccessorConverter.INSTANCE);
|
||||||
defaultConverterMap.put(LocalTime.class, TemporalAccessorConverter.INSTANCE);
|
converterMap.put(LocalTime.class, TemporalAccessorConverter.INSTANCE);
|
||||||
defaultConverterMap.put(ZonedDateTime.class, TemporalAccessorConverter.INSTANCE);
|
converterMap.put(ZonedDateTime.class, TemporalAccessorConverter.INSTANCE);
|
||||||
defaultConverterMap.put(OffsetDateTime.class, TemporalAccessorConverter.INSTANCE);
|
converterMap.put(OffsetDateTime.class, TemporalAccessorConverter.INSTANCE);
|
||||||
defaultConverterMap.put(OffsetTime.class, TemporalAccessorConverter.INSTANCE);
|
converterMap.put(OffsetTime.class, TemporalAccessorConverter.INSTANCE);
|
||||||
defaultConverterMap.put(DayOfWeek.class, TemporalAccessorConverter.INSTANCE);
|
converterMap.put(DayOfWeek.class, TemporalAccessorConverter.INSTANCE);
|
||||||
defaultConverterMap.put(Month.class, TemporalAccessorConverter.INSTANCE);
|
converterMap.put(Month.class, TemporalAccessorConverter.INSTANCE);
|
||||||
defaultConverterMap.put(MonthDay.class, TemporalAccessorConverter.INSTANCE);
|
converterMap.put(MonthDay.class, TemporalAccessorConverter.INSTANCE);
|
||||||
|
|
||||||
defaultConverterMap.put(Period.class, new PeriodConverter());
|
converterMap.put(Period.class, new PeriodConverter());
|
||||||
defaultConverterMap.put(Duration.class, new DurationConverter());
|
converterMap.put(Duration.class, new DurationConverter());
|
||||||
|
|
||||||
// Reference
|
// Reference
|
||||||
defaultConverterMap.put(WeakReference.class, ReferenceConverter.INSTANCE);// since 3.0.8
|
final ReferenceConverter referenceConverter = new ReferenceConverter(rootConverter);
|
||||||
defaultConverterMap.put(SoftReference.class, ReferenceConverter.INSTANCE);// since 3.0.8
|
converterMap.put(WeakReference.class, referenceConverter);// since 3.0.8
|
||||||
defaultConverterMap.put(AtomicReference.class, new AtomicReferenceConverter());// since 3.0.8
|
converterMap.put(SoftReference.class, referenceConverter);// since 3.0.8
|
||||||
|
converterMap.put(AtomicReference.class, new AtomicReferenceConverter(rootConverter));// since 3.0.8
|
||||||
|
|
||||||
//AtomicXXXArray,since 5.4.5
|
//AtomicXXXArray,since 5.4.5
|
||||||
defaultConverterMap.put(AtomicIntegerArray.class, new AtomicIntegerArrayConverter());
|
converterMap.put(AtomicIntegerArray.class, new AtomicIntegerArrayConverter());
|
||||||
defaultConverterMap.put(AtomicLongArray.class, new AtomicLongArrayConverter());
|
converterMap.put(AtomicLongArray.class, new AtomicLongArrayConverter());
|
||||||
|
|
||||||
// 其它类型
|
// 其它类型
|
||||||
defaultConverterMap.put(Locale.class, new LocaleConverter());
|
converterMap.put(Locale.class, new LocaleConverter());
|
||||||
defaultConverterMap.put(Charset.class, new CharsetConverter());
|
converterMap.put(Charset.class, new CharsetConverter());
|
||||||
defaultConverterMap.put(Path.class, new PathConverter());
|
converterMap.put(Path.class, new PathConverter());
|
||||||
defaultConverterMap.put(Currency.class, new CurrencyConverter());// since 3.0.8
|
converterMap.put(Currency.class, new CurrencyConverter());// since 3.0.8
|
||||||
defaultConverterMap.put(UUID.class, new UUIDConverter());// since 4.0.10
|
converterMap.put(UUID.class, new UUIDConverter());// since 4.0.10
|
||||||
defaultConverterMap.put(StackTraceElement.class, new StackTraceElementConverter());// since 4.5.2
|
converterMap.put(StackTraceElement.class, new StackTraceElementConverter());// since 4.5.2
|
||||||
defaultConverterMap.put(Optional.class, new OptionalConverter());// since 5.0.0
|
converterMap.put(Optional.class, new OptionalConverter());// since 5.0.0
|
||||||
defaultConverterMap.put(Opt.class, new OptConverter());// since 5.7.16
|
converterMap.put(Opt.class, new OptConverter());// since 5.7.16
|
||||||
defaultConverterMap.put(Pair.class, PairConverter.INSTANCE);// since 6.0.0
|
converterMap.put(Pair.class, new PairConverter(rootConverter));// since 6.0.0
|
||||||
defaultConverterMap.put(Triple.class, TripleConverter.INSTANCE);// since 6.0.0
|
converterMap.put(Triple.class, new TripleConverter(rootConverter));// since 6.0.0
|
||||||
defaultConverterMap.put(Tuple.class, TupleConverter.INSTANCE);// since 6.0.0
|
converterMap.put(Tuple.class, TupleConverter.INSTANCE);// since 6.0.0
|
||||||
|
|
||||||
this.defaultConverterMap = defaultConverterMap;
|
return converterMap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package org.dromara.hutool.core.convert;
|
package org.dromara.hutool.core.convert;
|
||||||
|
|
||||||
import org.dromara.hutool.core.convert.impl.*;
|
import org.dromara.hutool.core.convert.impl.*;
|
||||||
|
import org.dromara.hutool.core.lang.Assert;
|
||||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||||
import org.dromara.hutool.core.stream.StreamUtil;
|
import org.dromara.hutool.core.stream.StreamUtil;
|
||||||
|
|
||||||
@ -33,28 +34,9 @@ import java.util.Set;
|
|||||||
* @author Looly
|
* @author Looly
|
||||||
* @since 6.0.0
|
* @since 6.0.0
|
||||||
*/
|
*/
|
||||||
public class SpecialConverter implements Converter, Serializable {
|
public class SpecialConverter extends ConverterWithRoot implements Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
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>
|
* 类型转换器集合<br>
|
||||||
* 此集合初始化后不再加入新值,因此单例使用线程安全
|
* 此集合初始化后不再加入新值,因此单例使用线程安全
|
||||||
@ -63,42 +45,12 @@ public class SpecialConverter implements Converter, Serializable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造
|
* 构造
|
||||||
|
*
|
||||||
|
* @param rootConverter 父转换器
|
||||||
*/
|
*/
|
||||||
private SpecialConverter() {
|
public SpecialConverter(final Converter rootConverter) {
|
||||||
final Set<MatcherConverter> converterSet = new LinkedHashSet<>(64);
|
super(rootConverter);
|
||||||
|
this.converterSet = initDefault(Assert.notNull(rootConverter));
|
||||||
// 集合转换(含有泛型参数,不可以默认强转)
|
|
||||||
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);
|
|
||||||
|
|
||||||
// 日期相关
|
|
||||||
converterSet.add(TimeZoneConverter.INSTANCE);
|
|
||||||
converterSet.add(ZoneIdConverter.INSTANCE);
|
|
||||||
|
|
||||||
this.converterSet = converterSet;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -141,4 +93,47 @@ public class SpecialConverter implements Converter, Serializable {
|
|||||||
private static Converter getConverterFromSet(final Set<? extends MatcherConverter> converterSet, final Type type, final Class<?> rawType, final Object value) {
|
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);
|
return StreamUtil.of(converterSet).filter((predicate) -> predicate.match(type, rawType, value)).findFirst().orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化默认转换器
|
||||||
|
*
|
||||||
|
* @param rootConverter 根转换器,用于递归子对象转换
|
||||||
|
* @return 转换器集合
|
||||||
|
*/
|
||||||
|
private static Set<MatcherConverter> initDefault(final Converter rootConverter) {
|
||||||
|
final Set<MatcherConverter> converterSet = new LinkedHashSet<>(64);
|
||||||
|
|
||||||
|
// 集合转换(含有泛型参数,不可以默认强转)
|
||||||
|
converterSet.add(CollectionConverter.INSTANCE);
|
||||||
|
// Map类型(含有泛型参数,不可以默认强转)
|
||||||
|
converterSet.add(new MapConverter(rootConverter));
|
||||||
|
// issue#I6SZYB Entry类(含有泛型参数,不可以默认强转)
|
||||||
|
converterSet.add(new EntryConverter(rootConverter));
|
||||||
|
// 默认强转
|
||||||
|
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);
|
||||||
|
|
||||||
|
// 日期相关
|
||||||
|
converterSet.add(TimeZoneConverter.INSTANCE);
|
||||||
|
converterSet.add(ZoneIdConverter.INSTANCE);
|
||||||
|
|
||||||
|
return converterSet;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
package org.dromara.hutool.core.convert.impl;
|
package org.dromara.hutool.core.convert.impl;
|
||||||
|
|
||||||
import org.dromara.hutool.core.convert.AbstractConverter;
|
import org.dromara.hutool.core.convert.AbstractConverter;
|
||||||
import org.dromara.hutool.core.convert.CompositeConverter;
|
import org.dromara.hutool.core.convert.Converter;
|
||||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
@ -32,16 +32,27 @@ import java.util.concurrent.atomic.AtomicReference;
|
|||||||
public class AtomicReferenceConverter extends AbstractConverter {
|
public class AtomicReferenceConverter extends AbstractConverter {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private final Converter converter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param converter 用于转换AtomicReference包装的对象类型
|
||||||
|
*/
|
||||||
|
public AtomicReferenceConverter(final Converter converter) {
|
||||||
|
this.converter = converter;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AtomicReference<?> convertInternal(final Class<?> targetClass, final Object value) {
|
protected AtomicReference<?> convertInternal(final Class<?> targetClass, final Object value) {
|
||||||
|
|
||||||
//尝试将值转换为Reference泛型的类型
|
//尝试将值转换为Reference泛型的类型
|
||||||
Object targetValue = null;
|
Object targetValue = null;
|
||||||
final Type paramType = TypeUtil.getTypeArgument(AtomicReference.class);
|
final Type paramType = TypeUtil.getTypeArgument(AtomicReference.class);
|
||||||
if(!TypeUtil.isUnknown(paramType)){
|
if (!TypeUtil.isUnknown(paramType)) {
|
||||||
targetValue = CompositeConverter.getInstance().convert(paramType, value);
|
targetValue = converter.convert(paramType, value);
|
||||||
}
|
}
|
||||||
if(null == targetValue){
|
if (null == targetValue) {
|
||||||
targetValue = value;
|
targetValue = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,8 +17,8 @@
|
|||||||
package org.dromara.hutool.core.convert.impl;
|
package org.dromara.hutool.core.convert.impl;
|
||||||
|
|
||||||
import org.dromara.hutool.core.bean.BeanUtil;
|
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.ConvertException;
|
||||||
|
import org.dromara.hutool.core.convert.Converter;
|
||||||
import org.dromara.hutool.core.convert.MatcherConverter;
|
import org.dromara.hutool.core.convert.MatcherConverter;
|
||||||
import org.dromara.hutool.core.lang.tuple.Pair;
|
import org.dromara.hutool.core.lang.tuple.Pair;
|
||||||
import org.dromara.hutool.core.map.MapUtil;
|
import org.dromara.hutool.core.map.MapUtil;
|
||||||
@ -46,10 +46,16 @@ import java.util.Map;
|
|||||||
public class EntryConverter implements MatcherConverter, Serializable {
|
public class EntryConverter implements MatcherConverter, Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private final Converter convert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 单例
|
* 构造
|
||||||
|
*
|
||||||
|
* @param converter 转换器,用于将Entry中key和value转换为指定类型的对象
|
||||||
*/
|
*/
|
||||||
public static final EntryConverter INSTANCE = new EntryConverter();
|
public EntryConverter(final Converter converter) {
|
||||||
|
this.convert = converter;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean match(final Type targetType, final Class<?> rawType, final Object value) {
|
public boolean match(final Type targetType, final Class<?> rawType, final Object value) {
|
||||||
@ -132,7 +138,7 @@ public class EntryConverter implements MatcherConverter, Serializable {
|
|||||||
* @return Entry
|
* @return Entry
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
private static Map.Entry<?, ?> mapToEntry(final Type targetType, final Type keyType, final Type valueType, final Map map) {
|
private Map.Entry<?, ?> mapToEntry(final Type targetType, final Type keyType, final Type valueType, final Map map) {
|
||||||
|
|
||||||
final Object key;
|
final Object key;
|
||||||
final Object value;
|
final Object value;
|
||||||
@ -146,7 +152,6 @@ public class EntryConverter implements MatcherConverter, Serializable {
|
|||||||
value = map.get("value");
|
value = map.get("value");
|
||||||
}
|
}
|
||||||
|
|
||||||
final CompositeConverter convert = CompositeConverter.getInstance();
|
|
||||||
return (Map.Entry<?, ?>) ConstructorUtil.newInstance(TypeUtil.getClass(targetType),
|
return (Map.Entry<?, ?>) ConstructorUtil.newInstance(TypeUtil.getClass(targetType),
|
||||||
TypeUtil.isUnknown(keyType) ? key : convert.convert(keyType, key),
|
TypeUtil.isUnknown(keyType) ? key : convert.convert(keyType, key),
|
||||||
TypeUtil.isUnknown(valueType) ? value : convert.convert(valueType, value)
|
TypeUtil.isUnknown(valueType) ? value : convert.convert(valueType, value)
|
||||||
|
@ -17,9 +17,7 @@
|
|||||||
package org.dromara.hutool.core.convert.impl;
|
package org.dromara.hutool.core.convert.impl;
|
||||||
|
|
||||||
import org.dromara.hutool.core.bean.BeanUtil;
|
import org.dromara.hutool.core.bean.BeanUtil;
|
||||||
import org.dromara.hutool.core.convert.CompositeConverter;
|
import org.dromara.hutool.core.convert.*;
|
||||||
import org.dromara.hutool.core.convert.ConvertException;
|
|
||||||
import org.dromara.hutool.core.convert.MatcherConverter;
|
|
||||||
import org.dromara.hutool.core.map.MapUtil;
|
import org.dromara.hutool.core.map.MapUtil;
|
||||||
import org.dromara.hutool.core.reflect.TypeReference;
|
import org.dromara.hutool.core.reflect.TypeReference;
|
||||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||||
@ -40,13 +38,22 @@ import java.util.Objects;
|
|||||||
* @author Looly
|
* @author Looly
|
||||||
* @since 3.0.8
|
* @since 3.0.8
|
||||||
*/
|
*/
|
||||||
public class MapConverter implements MatcherConverter, Serializable {
|
public class MapConverter extends ConverterWithRoot implements MatcherConverter, Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 单例
|
* 单例
|
||||||
*/
|
*/
|
||||||
public static MapConverter INSTANCE = new MapConverter();
|
public static final MapConverter INSTANCE = new MapConverter(CompositeConverter.getInstance());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param rootConverter 根转换器,用于转换Map中键值对中的值,非{@code null}
|
||||||
|
*/
|
||||||
|
public MapConverter(final Converter rootConverter) {
|
||||||
|
super(rootConverter);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean match(final Type targetType, final Class<?> rawType, final Object value) {
|
public boolean match(final Type targetType, final Class<?> rawType, final Object value) {
|
||||||
@ -111,10 +118,9 @@ public class MapConverter implements MatcherConverter, Serializable {
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
private void convertMapToMap(final Type keyType, final Type valueType, final Map<?, ?> srcMap, final Map targetMap) {
|
private void convertMapToMap(final Type keyType, final Type valueType, final Map<?, ?> srcMap, final Map targetMap) {
|
||||||
final CompositeConverter convert = CompositeConverter.getInstance();
|
|
||||||
srcMap.forEach((key, value) -> targetMap.put(
|
srcMap.forEach((key, value) -> targetMap.put(
|
||||||
TypeUtil.isUnknown(keyType) ? key : convert.convert(keyType, key),
|
TypeUtil.isUnknown(keyType) ? key : rootConverter.convert(keyType, key),
|
||||||
TypeUtil.isUnknown(valueType) ? value : convert.convert(valueType, value)
|
TypeUtil.isUnknown(valueType) ? value : rootConverter.convert(valueType, value)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,9 +17,9 @@
|
|||||||
package org.dromara.hutool.core.convert.impl;
|
package org.dromara.hutool.core.convert.impl;
|
||||||
|
|
||||||
import org.dromara.hutool.core.bean.BeanUtil;
|
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.ConvertException;
|
||||||
import org.dromara.hutool.core.convert.Converter;
|
import org.dromara.hutool.core.convert.Converter;
|
||||||
|
import org.dromara.hutool.core.convert.ConverterWithRoot;
|
||||||
import org.dromara.hutool.core.lang.tuple.Pair;
|
import org.dromara.hutool.core.lang.tuple.Pair;
|
||||||
import org.dromara.hutool.core.map.MapUtil;
|
import org.dromara.hutool.core.map.MapUtil;
|
||||||
import org.dromara.hutool.core.reflect.TypeReference;
|
import org.dromara.hutool.core.reflect.TypeReference;
|
||||||
@ -27,6 +27,7 @@ import org.dromara.hutool.core.reflect.TypeUtil;
|
|||||||
import org.dromara.hutool.core.text.CharUtil;
|
import org.dromara.hutool.core.text.CharUtil;
|
||||||
import org.dromara.hutool.core.text.StrUtil;
|
import org.dromara.hutool.core.text.StrUtil;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -41,12 +42,17 @@ import java.util.Map;
|
|||||||
*
|
*
|
||||||
* @author looly
|
* @author looly
|
||||||
*/
|
*/
|
||||||
public class PairConverter implements Converter {
|
public class PairConverter extends ConverterWithRoot implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 单例
|
* 构造
|
||||||
|
*
|
||||||
|
* @param rootConverter 根转换器,用于转换Pair中的值
|
||||||
*/
|
*/
|
||||||
public static final PairConverter INSTANCE = new PairConverter();
|
public PairConverter(final Converter rootConverter) {
|
||||||
|
super(rootConverter);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object convert(Type targetType, final Object value) throws ConvertException {
|
public Object convert(Type targetType, final Object value) throws ConvertException {
|
||||||
@ -122,7 +128,7 @@ public class PairConverter implements Converter {
|
|||||||
* @return Pair
|
* @return Pair
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
private static Pair<?, ?> mapToPair(final Type keyType, final Type valueType, final Map map) {
|
private Pair<?, ?> mapToPair(final Type keyType, final Type valueType, final Map map) {
|
||||||
|
|
||||||
final Object left;
|
final Object left;
|
||||||
final Object right;
|
final Object right;
|
||||||
@ -136,10 +142,9 @@ public class PairConverter implements Converter {
|
|||||||
right = map.get("right");
|
right = map.get("right");
|
||||||
}
|
}
|
||||||
|
|
||||||
final CompositeConverter convert = CompositeConverter.getInstance();
|
|
||||||
return Pair.of(
|
return Pair.of(
|
||||||
TypeUtil.isUnknown(keyType) ? left : convert.convert(keyType, left),
|
TypeUtil.isUnknown(keyType) ? left : rootConverter.convert(keyType, left),
|
||||||
TypeUtil.isUnknown(valueType) ? right : convert.convert(valueType, right)
|
TypeUtil.isUnknown(valueType) ? right : rootConverter.convert(valueType, right)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,9 +17,10 @@
|
|||||||
package org.dromara.hutool.core.convert.impl;
|
package org.dromara.hutool.core.convert.impl;
|
||||||
|
|
||||||
import org.dromara.hutool.core.convert.AbstractConverter;
|
import org.dromara.hutool.core.convert.AbstractConverter;
|
||||||
import org.dromara.hutool.core.convert.CompositeConverter;
|
import org.dromara.hutool.core.convert.Converter;
|
||||||
import org.dromara.hutool.core.text.StrUtil;
|
import org.dromara.hutool.core.lang.Assert;
|
||||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||||
|
import org.dromara.hutool.core.text.StrUtil;
|
||||||
|
|
||||||
import java.lang.ref.Reference;
|
import java.lang.ref.Reference;
|
||||||
import java.lang.ref.SoftReference;
|
import java.lang.ref.SoftReference;
|
||||||
@ -36,10 +37,16 @@ import java.lang.reflect.Type;
|
|||||||
public class ReferenceConverter extends AbstractConverter {
|
public class ReferenceConverter extends AbstractConverter {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private final Converter rootConverter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 单例
|
* 构造
|
||||||
|
*
|
||||||
|
* @param rootConverter 根转换器,用于转换Reference泛型的类型
|
||||||
*/
|
*/
|
||||||
public static ReferenceConverter INSTANCE = new ReferenceConverter();
|
public ReferenceConverter(final Converter rootConverter) {
|
||||||
|
this.rootConverter = Assert.notNull(rootConverter);
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
@ -49,7 +56,7 @@ public class ReferenceConverter extends AbstractConverter {
|
|||||||
Object targetValue = null;
|
Object targetValue = null;
|
||||||
final Type paramType = TypeUtil.getTypeArgument(targetClass);
|
final Type paramType = TypeUtil.getTypeArgument(targetClass);
|
||||||
if(!TypeUtil.isUnknown(paramType)){
|
if(!TypeUtil.isUnknown(paramType)){
|
||||||
targetValue = CompositeConverter.getInstance().convert(paramType, value);
|
targetValue = rootConverter.convert(paramType, value);
|
||||||
}
|
}
|
||||||
if(null == targetValue){
|
if(null == targetValue){
|
||||||
targetValue = value;
|
targetValue = value;
|
||||||
|
@ -17,13 +17,14 @@
|
|||||||
package org.dromara.hutool.core.convert.impl;
|
package org.dromara.hutool.core.convert.impl;
|
||||||
|
|
||||||
import org.dromara.hutool.core.bean.BeanUtil;
|
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.ConvertException;
|
||||||
import org.dromara.hutool.core.convert.Converter;
|
import org.dromara.hutool.core.convert.Converter;
|
||||||
|
import org.dromara.hutool.core.convert.ConverterWithRoot;
|
||||||
import org.dromara.hutool.core.lang.tuple.Triple;
|
import org.dromara.hutool.core.lang.tuple.Triple;
|
||||||
import org.dromara.hutool.core.reflect.TypeReference;
|
import org.dromara.hutool.core.reflect.TypeReference;
|
||||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -36,12 +37,17 @@ import java.util.Map;
|
|||||||
* @author looly
|
* @author looly
|
||||||
* @since 6.0.0
|
* @since 6.0.0
|
||||||
*/
|
*/
|
||||||
public class TripleConverter implements Converter {
|
public class TripleConverter extends ConverterWithRoot implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 单例
|
* 构造
|
||||||
|
*
|
||||||
|
* @param rootConverter 根转换器,用于转换无法被识别的对象
|
||||||
*/
|
*/
|
||||||
public static final TripleConverter INSTANCE = new TripleConverter();
|
public TripleConverter(final Converter rootConverter) {
|
||||||
|
super(rootConverter);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object convert(Type targetType, final Object value) throws ConvertException {
|
public Object convert(Type targetType, final Object value) throws ConvertException {
|
||||||
@ -69,9 +75,9 @@ public class TripleConverter implements Converter {
|
|||||||
public Triple<?, ?, ?> convert(final Type leftType, final Type middleType, final Type rightType, final Object value)
|
public Triple<?, ?, ?> convert(final Type leftType, final Type middleType, final Type rightType, final Object value)
|
||||||
throws ConvertException {
|
throws ConvertException {
|
||||||
Map map = null;
|
Map map = null;
|
||||||
if(value instanceof Map){
|
if (value instanceof Map) {
|
||||||
map = (Map) value;
|
map = (Map) value;
|
||||||
}else if (BeanUtil.isReadableBean(value.getClass())) {
|
} else if (BeanUtil.isReadableBean(value.getClass())) {
|
||||||
// 一次性只读场景,包装为Map效率更高
|
// 一次性只读场景,包装为Map效率更高
|
||||||
map = BeanUtil.toBeanMap(value);
|
map = BeanUtil.toBeanMap(value);
|
||||||
}
|
}
|
||||||
@ -92,17 +98,16 @@ public class TripleConverter implements Converter {
|
|||||||
* @return Entry
|
* @return Entry
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
private static Triple<?, ?, ?> mapToTriple(final Type leftType, final Type middleType, final Type rightType, final Map map) {
|
private Triple<?, ?, ?> mapToTriple(final Type leftType, final Type middleType, final Type rightType, final Map map) {
|
||||||
|
|
||||||
final Object left = map.get("left");
|
final Object left = map.get("left");
|
||||||
final Object middle = map.get("middle");
|
final Object middle = map.get("middle");
|
||||||
final Object right = map.get("right");
|
final Object right = map.get("right");
|
||||||
|
|
||||||
final CompositeConverter convert = CompositeConverter.getInstance();
|
|
||||||
return Triple.of(
|
return Triple.of(
|
||||||
TypeUtil.isUnknown(leftType) ? left : convert.convert(leftType, left),
|
TypeUtil.isUnknown(leftType) ? left : rootConverter.convert(leftType, left),
|
||||||
TypeUtil.isUnknown(middleType) ? middle : convert.convert(middleType, middle),
|
TypeUtil.isUnknown(middleType) ? middle : rootConverter.convert(middleType, middle),
|
||||||
TypeUtil.isUnknown(rightType) ? right : convert.convert(rightType, right)
|
TypeUtil.isUnknown(rightType) ? right : rootConverter.convert(rightType, right)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,10 +16,10 @@
|
|||||||
|
|
||||||
package org.dromara.hutool.core.lang;
|
package org.dromara.hutool.core.lang;
|
||||||
|
|
||||||
|
import org.dromara.hutool.core.array.ArrayUtil;
|
||||||
import org.dromara.hutool.core.collection.CollUtil;
|
import org.dromara.hutool.core.collection.CollUtil;
|
||||||
import org.dromara.hutool.core.map.MapUtil;
|
import org.dromara.hutool.core.map.MapUtil;
|
||||||
import org.dromara.hutool.core.text.StrUtil;
|
import org.dromara.hutool.core.text.StrUtil;
|
||||||
import org.dromara.hutool.core.array.ArrayUtil;
|
|
||||||
import org.dromara.hutool.core.util.ObjUtil;
|
import org.dromara.hutool.core.util.ObjUtil;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -35,6 +35,7 @@ public class Assert {
|
|||||||
|
|
||||||
private static final String TEMPLATE_VALUE_MUST_BE_BETWEEN_AND = "The value must be between {} and {}.";
|
private static final String TEMPLATE_VALUE_MUST_BE_BETWEEN_AND = "The value must be between {} and {}.";
|
||||||
|
|
||||||
|
// region ----- isTrue and isFalse
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 断言是否为真,如果为 {@code false} 抛出给定的异常<br>
|
* 断言是否为真,如果为 {@code false} 抛出给定的异常<br>
|
||||||
@ -135,6 +136,9 @@ public class Assert {
|
|||||||
public static void isFalse(final boolean expression) throws IllegalArgumentException {
|
public static void isFalse(final boolean expression) throws IllegalArgumentException {
|
||||||
isFalse(expression, "[Assertion failed] - this expression must be false");
|
isFalse(expression, "[Assertion failed] - this expression must be false");
|
||||||
}
|
}
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region ----- isNull or notNull
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 断言对象是否为{@code null} ,如果不为{@code null} 抛出指定类型异常
|
* 断言对象是否为{@code null} ,如果不为{@code null} 抛出指定类型异常
|
||||||
@ -186,8 +190,6 @@ public class Assert {
|
|||||||
isNull(object, "[Assertion failed] - the object argument must be null");
|
isNull(object, "[Assertion failed] - the object argument must be null");
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------------------------------- Check not null
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 断言对象是否不为{@code null} ,如果为{@code null} 抛出指定类型异常
|
* 断言对象是否不为{@code null} ,如果为{@code null} 抛出指定类型异常
|
||||||
* 并使用指定的函数获取错误信息返回
|
* 并使用指定的函数获取错误信息返回
|
||||||
@ -214,10 +216,10 @@ public class Assert {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 断言对象是否不为{@code null} ,如果为{@code null} 抛出{@link IllegalArgumentException} 异常 Assert that an object is not {@code null} .
|
* 断言对象是否不为{@code null} ,如果为{@code null} 抛出{@link IllegalArgumentException}
|
||||||
* <pre class="code">
|
* <pre>{@code
|
||||||
* Assert.notNull(clazz, "The class must not be null");
|
* Assert.notNull(clazz, "The class must not be null");
|
||||||
* </pre>
|
* }</pre>
|
||||||
*
|
*
|
||||||
* @param <T> 被检查对象泛型类型
|
* @param <T> 被检查对象泛型类型
|
||||||
* @param object 被检查对象
|
* @param object 被检查对象
|
||||||
@ -227,14 +229,17 @@ public class Assert {
|
|||||||
* @throws IllegalArgumentException if the object is {@code null}
|
* @throws IllegalArgumentException if the object is {@code null}
|
||||||
*/
|
*/
|
||||||
public static <T> T notNull(final T object, final String errorMsgTemplate, final Object... params) throws IllegalArgumentException {
|
public static <T> T notNull(final T object, final String errorMsgTemplate, final Object... params) throws IllegalArgumentException {
|
||||||
return notNull(object, () -> new IllegalArgumentException(StrUtil.format(errorMsgTemplate, params)));
|
if (null == object) {
|
||||||
|
throw new IllegalArgumentException(StrUtil.format(errorMsgTemplate, params));
|
||||||
|
}
|
||||||
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 断言对象是否不为{@code null} ,如果为{@code null} 抛出{@link IllegalArgumentException} 异常
|
* 断言对象是否不为{@code null} ,如果为{@code null} 抛出{@link IllegalArgumentException} 异常
|
||||||
* <pre class="code">
|
* <pre>{@code
|
||||||
* Assert.notNull(clazz);
|
* Assert.notNull(clazz);
|
||||||
* </pre>
|
* }</pre>
|
||||||
*
|
*
|
||||||
* @param <T> 被检查对象类型
|
* @param <T> 被检查对象类型
|
||||||
* @param object 被检查对象
|
* @param object 被检查对象
|
||||||
@ -242,193 +247,14 @@ public class Assert {
|
|||||||
* @throws IllegalArgumentException if the object is {@code null}
|
* @throws IllegalArgumentException if the object is {@code null}
|
||||||
*/
|
*/
|
||||||
public static <T> T notNull(final T object) throws IllegalArgumentException {
|
public static <T> T notNull(final T object) throws IllegalArgumentException {
|
||||||
return notNull(object, "[Assertion failed] - this argument is required; it must not be null");
|
if (null == object) {
|
||||||
}
|
throw new IllegalArgumentException("[Assertion failed] - this argument is required; it must not be null");
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------------------------------- Check empty
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查给定字符串是否为空,为空抛出自定义异常,并使用指定的函数获取错误信息返回。
|
|
||||||
* <pre class="code">
|
|
||||||
* Assert.notEmpty(name, ()->{
|
|
||||||
* // to query relation message
|
|
||||||
* return new IllegalArgumentException("relation message to return");
|
|
||||||
* });
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @param <X> 异常类型
|
|
||||||
* @param <T> 字符串类型
|
|
||||||
* @param text 被检查字符串
|
|
||||||
* @param errorSupplier 错误抛出异常附带的消息生产接口
|
|
||||||
* @return 非空字符串
|
|
||||||
* @throws X 被检查字符串为空抛出此异常
|
|
||||||
* @see StrUtil#isNotEmpty(CharSequence)
|
|
||||||
* @since 5.4.5
|
|
||||||
*/
|
|
||||||
public static <T extends CharSequence, X extends Throwable> T notEmpty(final T text, final Supplier<X> errorSupplier) throws X {
|
|
||||||
if (StrUtil.isEmpty(text)) {
|
|
||||||
throw errorSupplier.get();
|
|
||||||
}
|
}
|
||||||
return text;
|
return object;
|
||||||
}
|
}
|
||||||
|
// endregion
|
||||||
|
|
||||||
/**
|
// region ----- notEmpty and notBlank
|
||||||
* 检查给定字符串是否为空,为空抛出 {@link IllegalArgumentException}
|
|
||||||
*
|
|
||||||
* <pre class="code">
|
|
||||||
* Assert.notEmpty(name, "Name must not be empty");
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @param <T> 字符串类型
|
|
||||||
* @param text 被检查字符串
|
|
||||||
* @param errorMsgTemplate 错误消息模板,变量使用{}表示
|
|
||||||
* @param params 参数
|
|
||||||
* @return 非空字符串
|
|
||||||
* @throws IllegalArgumentException 被检查字符串为空
|
|
||||||
* @see StrUtil#isNotEmpty(CharSequence)
|
|
||||||
*/
|
|
||||||
public static <T extends CharSequence> T notEmpty(final T text, final String errorMsgTemplate, final Object... params) throws IllegalArgumentException {
|
|
||||||
return notEmpty(text, () -> new IllegalArgumentException(StrUtil.format(errorMsgTemplate, params)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查给定字符串是否为空,为空抛出 {@link IllegalArgumentException}
|
|
||||||
*
|
|
||||||
* <pre class="code">
|
|
||||||
* Assert.notEmpty(name);
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @param <T> 字符串类型
|
|
||||||
* @param text 被检查字符串
|
|
||||||
* @return 被检查的字符串
|
|
||||||
* @throws IllegalArgumentException 被检查字符串为空
|
|
||||||
* @see StrUtil#isNotEmpty(CharSequence)
|
|
||||||
*/
|
|
||||||
public static <T extends CharSequence> T notEmpty(final T text) throws IllegalArgumentException {
|
|
||||||
return notEmpty(text, "[Assertion failed] - this String argument must have length; it must not be null or empty");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查给定字符串是否为空白(null、空串或只包含空白符),为空抛出自定义异常。
|
|
||||||
* 并使用指定的函数获取错误信息返回
|
|
||||||
* <pre class="code">
|
|
||||||
* Assert.notBlank(name, ()->{
|
|
||||||
* // to query relation message
|
|
||||||
* return new IllegalArgumentException("relation message to return");
|
|
||||||
* });
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @param <X> 异常类型
|
|
||||||
* @param <T> 字符串类型
|
|
||||||
* @param text 被检查字符串
|
|
||||||
* @param errorMsgSupplier 错误抛出异常附带的消息生产接口
|
|
||||||
* @return 非空字符串
|
|
||||||
* @throws X 被检查字符串为空白
|
|
||||||
* @see StrUtil#isNotBlank(CharSequence)
|
|
||||||
*/
|
|
||||||
public static <T extends CharSequence, X extends Throwable> T notBlank(final T text, final Supplier<X> errorMsgSupplier) throws X {
|
|
||||||
if (StrUtil.isBlank(text)) {
|
|
||||||
throw errorMsgSupplier.get();
|
|
||||||
}
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查给定字符串是否为空白(null、空串或只包含空白符),为空抛出 {@link IllegalArgumentException}
|
|
||||||
*
|
|
||||||
* <pre class="code">
|
|
||||||
* Assert.notBlank(name, "Name must not be blank");
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @param <T> 字符串类型
|
|
||||||
* @param text 被检查字符串
|
|
||||||
* @param errorMsgTemplate 错误消息模板,变量使用{}表示
|
|
||||||
* @param params 参数
|
|
||||||
* @return 非空字符串
|
|
||||||
* @throws IllegalArgumentException 被检查字符串为空白
|
|
||||||
* @see StrUtil#isNotBlank(CharSequence)
|
|
||||||
*/
|
|
||||||
public static <T extends CharSequence> T notBlank(final T text, final String errorMsgTemplate, final Object... params) throws IllegalArgumentException {
|
|
||||||
return notBlank(text, () -> new IllegalArgumentException(StrUtil.format(errorMsgTemplate, params)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查给定字符串是否为空白(null、空串或只包含空白符),为空抛出 {@link IllegalArgumentException}
|
|
||||||
*
|
|
||||||
* <pre class="code">
|
|
||||||
* Assert.notBlank(name);
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @param <T> 字符串类型
|
|
||||||
* @param text 被检查字符串
|
|
||||||
* @return 非空字符串
|
|
||||||
* @throws IllegalArgumentException 被检查字符串为空白
|
|
||||||
* @see StrUtil#isNotBlank(CharSequence)
|
|
||||||
*/
|
|
||||||
public static <T extends CharSequence> T notBlank(final T text) throws IllegalArgumentException {
|
|
||||||
return notBlank(text, "[Assertion failed] - this String argument must have text; it must not be null, empty, or blank");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 断言给定字符串是否不被另一个字符串包含(即是否为子串),并使用指定的函数获取错误信息返回<br>
|
|
||||||
* 如果非子串,返回子串,如果是子串,则抛出{@link IllegalArgumentException}异常。
|
|
||||||
* <pre class="code">
|
|
||||||
* Assert.notContain(name, "rod", ()->{
|
|
||||||
* // to query relation message
|
|
||||||
* return new IllegalArgumentException("relation message to return ");
|
|
||||||
* });
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @param <T> 字符串类型
|
|
||||||
* @param <X> 异常类型
|
|
||||||
* @param textToSearch 被搜索的字符串
|
|
||||||
* @param substring 被检查的子串
|
|
||||||
* @param errorSupplier 错误抛出异常附带的消息生产接口
|
|
||||||
* @return 被检查的子串
|
|
||||||
* @throws X 非子串抛出异常
|
|
||||||
* @see StrUtil#contains(CharSequence, CharSequence)
|
|
||||||
* @since 5.4.5
|
|
||||||
*/
|
|
||||||
public static <T extends CharSequence, X extends Throwable> T notContain(final CharSequence textToSearch, final T substring, final Supplier<X> errorSupplier) throws X {
|
|
||||||
if (StrUtil.contains(textToSearch, substring)) {
|
|
||||||
throw errorSupplier.get();
|
|
||||||
}
|
|
||||||
return substring;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 断言给定字符串是否不被另一个字符串包含(即是否为子串)<br>
|
|
||||||
* 如果非子串,返回子串,如果是子串,则抛出{@link IllegalArgumentException}异常。
|
|
||||||
* <pre class="code">
|
|
||||||
* Assert.notContain(name, "rod", "Name must not contain 'rod'");
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @param textToSearch 被搜索的字符串
|
|
||||||
* @param subString 被检查的子串
|
|
||||||
* @param errorMsgTemplate 异常时的消息模板
|
|
||||||
* @param params 参数列表
|
|
||||||
* @return 被检查的子串
|
|
||||||
* @throws IllegalArgumentException 非子串抛出异常
|
|
||||||
*/
|
|
||||||
public static String notContain(final String textToSearch, final String subString, final String errorMsgTemplate, final Object... params) throws IllegalArgumentException {
|
|
||||||
return notContain(textToSearch, subString, () -> new IllegalArgumentException(StrUtil.format(errorMsgTemplate, params)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 断言给定字符串是否不被另一个字符串包含(即是否为子串),即subString是否不是textToSearch的子串。<br>
|
|
||||||
* 如果非子串,返回子串,如果是子串,则抛出{@link IllegalArgumentException}异常。
|
|
||||||
* <pre class="code">
|
|
||||||
* Assert.notContain(name, "rod");
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @param textToSearch 被搜索的字符串
|
|
||||||
* @param subString 被检查的子串
|
|
||||||
* @return 被检查的子串
|
|
||||||
* @throws IllegalArgumentException 非子串抛出异常
|
|
||||||
*/
|
|
||||||
public static String notContain(final String textToSearch, final String subString) throws IllegalArgumentException {
|
|
||||||
return notContain(textToSearch, subString, "[Assertion failed] - this String argument must not contain the substring [{}]", subString);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 断言给定数组是否包含元素,数组必须不为 {@code null} 且至少包含一个元素
|
* 断言给定数组是否包含元素,数组必须不为 {@code null} 且至少包含一个元素
|
||||||
@ -488,64 +314,6 @@ public class Assert {
|
|||||||
return notEmpty(array, "[Assertion failed] - this array must not be empty: it must contain at least 1 element");
|
return notEmpty(array, "[Assertion failed] - this array must not be empty: it must contain at least 1 element");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 断言给定数组是否不包含{@code null}元素,如果数组为空或 {@code null}将被认为不包含
|
|
||||||
* 并使用指定的函数获取错误信息返回
|
|
||||||
* <pre class="code">
|
|
||||||
* Assert.noNullElements(array, ()->{
|
|
||||||
* // to query relation message
|
|
||||||
* return new IllegalArgumentException("relation message to return ");
|
|
||||||
* });
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @param <T> 数组元素类型
|
|
||||||
* @param <X> 异常类型
|
|
||||||
* @param array 被检查的数组
|
|
||||||
* @param errorSupplier 错误抛出异常附带的消息生产接口
|
|
||||||
* @return 被检查的数组
|
|
||||||
* @throws X if the object array contains a {@code null} element
|
|
||||||
* @see ArrayUtil#hasNull(Object[])
|
|
||||||
* @since 5.4.5
|
|
||||||
*/
|
|
||||||
public static <T, X extends Throwable> T[] noNullElements(final T[] array, final Supplier<X> errorSupplier) throws X {
|
|
||||||
if (ArrayUtil.hasNull(array)) {
|
|
||||||
throw errorSupplier.get();
|
|
||||||
}
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 断言给定数组是否不包含{@code null}元素,如果数组为空或 {@code null}将被认为不包含
|
|
||||||
* <pre class="code">
|
|
||||||
* Assert.noNullElements(array, "The array must not have null elements");
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @param <T> 数组元素类型
|
|
||||||
* @param array 被检查的数组
|
|
||||||
* @param errorMsgTemplate 异常时的消息模板
|
|
||||||
* @param params 参数列表
|
|
||||||
* @return 被检查的数组
|
|
||||||
* @throws IllegalArgumentException if the object array contains a {@code null} element
|
|
||||||
*/
|
|
||||||
public static <T> T[] noNullElements(final T[] array, final String errorMsgTemplate, final Object... params) throws IllegalArgumentException {
|
|
||||||
return noNullElements(array, () -> new IllegalArgumentException(StrUtil.format(errorMsgTemplate, params)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 断言给定数组是否不包含{@code null}元素,如果数组为空或 {@code null}将被认为不包含
|
|
||||||
* <pre class="code">
|
|
||||||
* Assert.noNullElements(array);
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @param <T> 数组元素类型
|
|
||||||
* @param array 被检查的数组
|
|
||||||
* @return 被检查的数组
|
|
||||||
* @throws IllegalArgumentException if the object array contains a {@code null} element
|
|
||||||
*/
|
|
||||||
public static <T> T[] noNullElements(final T[] array) throws IllegalArgumentException {
|
|
||||||
return noNullElements(array, "[Assertion failed] - this array must not contain any null elements");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 断言给定集合非空
|
* 断言给定集合非空
|
||||||
* 并使用指定的函数获取错误信息返回
|
* 并使用指定的函数获取错误信息返回
|
||||||
@ -671,6 +439,255 @@ public class Assert {
|
|||||||
return notEmpty(map, "[Assertion failed] - this map must not be empty; it must contain at least one entry");
|
return notEmpty(map, "[Assertion failed] - this map must not be empty; it must contain at least one entry");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查给定字符串是否为空,为空抛出自定义异常,并使用指定的函数获取错误信息返回。
|
||||||
|
* <pre class="code">
|
||||||
|
* Assert.notEmpty(name, ()->{
|
||||||
|
* // to query relation message
|
||||||
|
* return new IllegalArgumentException("relation message to return");
|
||||||
|
* });
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param <X> 异常类型
|
||||||
|
* @param <T> 字符串类型
|
||||||
|
* @param text 被检查字符串
|
||||||
|
* @param errorSupplier 错误抛出异常附带的消息生产接口
|
||||||
|
* @return 非空字符串
|
||||||
|
* @throws X 被检查字符串为空抛出此异常
|
||||||
|
* @see StrUtil#isNotEmpty(CharSequence)
|
||||||
|
* @since 5.4.5
|
||||||
|
*/
|
||||||
|
public static <T extends CharSequence, X extends Throwable> T notEmpty(final T text, final Supplier<X> errorSupplier) throws X {
|
||||||
|
if (StrUtil.isEmpty(text)) {
|
||||||
|
throw errorSupplier.get();
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查给定字符串是否为空,为空抛出 {@link IllegalArgumentException}
|
||||||
|
*
|
||||||
|
* <pre class="code">
|
||||||
|
* Assert.notEmpty(name, "Name must not be empty");
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param <T> 字符串类型
|
||||||
|
* @param text 被检查字符串
|
||||||
|
* @param errorMsgTemplate 错误消息模板,变量使用{}表示
|
||||||
|
* @param params 参数
|
||||||
|
* @return 非空字符串
|
||||||
|
* @throws IllegalArgumentException 被检查字符串为空
|
||||||
|
* @see StrUtil#isNotEmpty(CharSequence)
|
||||||
|
*/
|
||||||
|
public static <T extends CharSequence> T notEmpty(final T text, final String errorMsgTemplate, final Object... params) throws IllegalArgumentException {
|
||||||
|
return notEmpty(text, () -> new IllegalArgumentException(StrUtil.format(errorMsgTemplate, params)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查给定字符串是否为空,为空抛出 {@link IllegalArgumentException}
|
||||||
|
*
|
||||||
|
* <pre class="code">
|
||||||
|
* Assert.notEmpty(name);
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param <T> 字符串类型
|
||||||
|
* @param text 被检查字符串
|
||||||
|
* @return 被检查的字符串
|
||||||
|
* @throws IllegalArgumentException 被检查字符串为空
|
||||||
|
* @see StrUtil#isNotEmpty(CharSequence)
|
||||||
|
*/
|
||||||
|
public static <T extends CharSequence> T notEmpty(final T text) throws IllegalArgumentException {
|
||||||
|
return notEmpty(text, "[Assertion failed] - this String argument must have length; it must not be null or empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查给定字符串是否为空白(null、空串或只包含空白符),为空抛出自定义异常。
|
||||||
|
* 并使用指定的函数获取错误信息返回
|
||||||
|
* <pre class="code">
|
||||||
|
* Assert.notBlank(name, ()->{
|
||||||
|
* // to query relation message
|
||||||
|
* return new IllegalArgumentException("relation message to return");
|
||||||
|
* });
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param <X> 异常类型
|
||||||
|
* @param <T> 字符串类型
|
||||||
|
* @param text 被检查字符串
|
||||||
|
* @param errorMsgSupplier 错误抛出异常附带的消息生产接口
|
||||||
|
* @return 非空字符串
|
||||||
|
* @throws X 被检查字符串为空白
|
||||||
|
* @see StrUtil#isNotBlank(CharSequence)
|
||||||
|
*/
|
||||||
|
public static <T extends CharSequence, X extends Throwable> T notBlank(final T text, final Supplier<X> errorMsgSupplier) throws X {
|
||||||
|
if (StrUtil.isBlank(text)) {
|
||||||
|
throw errorMsgSupplier.get();
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查给定字符串是否为空白(null、空串或只包含空白符),为空抛出 {@link IllegalArgumentException}
|
||||||
|
*
|
||||||
|
* <pre class="code">
|
||||||
|
* Assert.notBlank(name, "Name must not be blank");
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param <T> 字符串类型
|
||||||
|
* @param text 被检查字符串
|
||||||
|
* @param errorMsgTemplate 错误消息模板,变量使用{}表示
|
||||||
|
* @param params 参数
|
||||||
|
* @return 非空字符串
|
||||||
|
* @throws IllegalArgumentException 被检查字符串为空白
|
||||||
|
* @see StrUtil#isNotBlank(CharSequence)
|
||||||
|
*/
|
||||||
|
public static <T extends CharSequence> T notBlank(final T text, final String errorMsgTemplate, final Object... params) throws IllegalArgumentException {
|
||||||
|
return notBlank(text, () -> new IllegalArgumentException(StrUtil.format(errorMsgTemplate, params)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查给定字符串是否为空白(null、空串或只包含空白符),为空抛出 {@link IllegalArgumentException}
|
||||||
|
*
|
||||||
|
* <pre class="code">
|
||||||
|
* Assert.notBlank(name);
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param <T> 字符串类型
|
||||||
|
* @param text 被检查字符串
|
||||||
|
* @return 非空字符串
|
||||||
|
* @throws IllegalArgumentException 被检查字符串为空白
|
||||||
|
* @see StrUtil#isNotBlank(CharSequence)
|
||||||
|
*/
|
||||||
|
public static <T extends CharSequence> T notBlank(final T text) throws IllegalArgumentException {
|
||||||
|
return notBlank(text, "[Assertion failed] - this String argument must have text; it must not be null, empty, or blank");
|
||||||
|
}
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region ----- notContain
|
||||||
|
/**
|
||||||
|
* 断言给定字符串是否不被另一个字符串包含(即是否为子串),并使用指定的函数获取错误信息返回<br>
|
||||||
|
* 如果非子串,返回子串,如果是子串,则抛出{@link IllegalArgumentException}异常。
|
||||||
|
* <pre class="code">
|
||||||
|
* Assert.notContain(name, "rod", ()->{
|
||||||
|
* // to query relation message
|
||||||
|
* return new IllegalArgumentException("relation message to return ");
|
||||||
|
* });
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param <T> 字符串类型
|
||||||
|
* @param <X> 异常类型
|
||||||
|
* @param textToSearch 被搜索的字符串
|
||||||
|
* @param substring 被检查的子串
|
||||||
|
* @param errorSupplier 错误抛出异常附带的消息生产接口
|
||||||
|
* @return 被检查的子串
|
||||||
|
* @throws X 非子串抛出异常
|
||||||
|
* @see StrUtil#contains(CharSequence, CharSequence)
|
||||||
|
* @since 5.4.5
|
||||||
|
*/
|
||||||
|
public static <T extends CharSequence, X extends Throwable> T notContain(final CharSequence textToSearch, final T substring, final Supplier<X> errorSupplier) throws X {
|
||||||
|
if (StrUtil.contains(textToSearch, substring)) {
|
||||||
|
throw errorSupplier.get();
|
||||||
|
}
|
||||||
|
return substring;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言给定字符串是否不被另一个字符串包含(即是否为子串)<br>
|
||||||
|
* 如果非子串,返回子串,如果是子串,则抛出{@link IllegalArgumentException}异常。
|
||||||
|
* <pre class="code">
|
||||||
|
* Assert.notContain(name, "rod", "Name must not contain 'rod'");
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param textToSearch 被搜索的字符串
|
||||||
|
* @param subString 被检查的子串
|
||||||
|
* @param errorMsgTemplate 异常时的消息模板
|
||||||
|
* @param params 参数列表
|
||||||
|
* @return 被检查的子串
|
||||||
|
* @throws IllegalArgumentException 非子串抛出异常
|
||||||
|
*/
|
||||||
|
public static String notContain(final String textToSearch, final String subString, final String errorMsgTemplate, final Object... params) throws IllegalArgumentException {
|
||||||
|
return notContain(textToSearch, subString, () -> new IllegalArgumentException(StrUtil.format(errorMsgTemplate, params)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言给定字符串是否不被另一个字符串包含(即是否为子串),即subString是否不是textToSearch的子串。<br>
|
||||||
|
* 如果非子串,返回子串,如果是子串,则抛出{@link IllegalArgumentException}异常。
|
||||||
|
* <pre class="code">
|
||||||
|
* Assert.notContain(name, "rod");
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param textToSearch 被搜索的字符串
|
||||||
|
* @param subString 被检查的子串
|
||||||
|
* @return 被检查的子串
|
||||||
|
* @throws IllegalArgumentException 非子串抛出异常
|
||||||
|
*/
|
||||||
|
public static String notContain(final String textToSearch, final String subString) throws IllegalArgumentException {
|
||||||
|
return notContain(textToSearch, subString, "[Assertion failed] - this String argument must not contain the substring [{}]", subString);
|
||||||
|
}
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region ----- noNullElements
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言给定数组是否不包含{@code null}元素,如果数组为空或 {@code null}将被认为不包含
|
||||||
|
* 并使用指定的函数获取错误信息返回
|
||||||
|
* <pre class="code">
|
||||||
|
* Assert.noNullElements(array, ()->{
|
||||||
|
* // to query relation message
|
||||||
|
* return new IllegalArgumentException("relation message to return ");
|
||||||
|
* });
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param <T> 数组元素类型
|
||||||
|
* @param <X> 异常类型
|
||||||
|
* @param array 被检查的数组
|
||||||
|
* @param errorSupplier 错误抛出异常附带的消息生产接口
|
||||||
|
* @return 被检查的数组
|
||||||
|
* @throws X if the object array contains a {@code null} element
|
||||||
|
* @see ArrayUtil#hasNull(Object[])
|
||||||
|
* @since 5.4.5
|
||||||
|
*/
|
||||||
|
public static <T, X extends Throwable> T[] noNullElements(final T[] array, final Supplier<X> errorSupplier) throws X {
|
||||||
|
if (ArrayUtil.hasNull(array)) {
|
||||||
|
throw errorSupplier.get();
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言给定数组是否不包含{@code null}元素,如果数组为空或 {@code null}将被认为不包含
|
||||||
|
* <pre class="code">
|
||||||
|
* Assert.noNullElements(array, "The array must not have null elements");
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param <T> 数组元素类型
|
||||||
|
* @param array 被检查的数组
|
||||||
|
* @param errorMsgTemplate 异常时的消息模板
|
||||||
|
* @param params 参数列表
|
||||||
|
* @return 被检查的数组
|
||||||
|
* @throws IllegalArgumentException if the object array contains a {@code null} element
|
||||||
|
*/
|
||||||
|
public static <T> T[] noNullElements(final T[] array, final String errorMsgTemplate, final Object... params) throws IllegalArgumentException {
|
||||||
|
return noNullElements(array, () -> new IllegalArgumentException(StrUtil.format(errorMsgTemplate, params)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言给定数组是否不包含{@code null}元素,如果数组为空或 {@code null}将被认为不包含
|
||||||
|
* <pre class="code">
|
||||||
|
* Assert.noNullElements(array);
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param <T> 数组元素类型
|
||||||
|
* @param array 被检查的数组
|
||||||
|
* @return 被检查的数组
|
||||||
|
* @throws IllegalArgumentException if the object array contains a {@code null} element
|
||||||
|
*/
|
||||||
|
public static <T> T[] noNullElements(final T[] array) throws IllegalArgumentException {
|
||||||
|
return noNullElements(array, "[Assertion failed] - this array must not contain any null elements");
|
||||||
|
}
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region ----- isInstanceOf and isAssignable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 断言给定对象是否是给定类的实例
|
* 断言给定对象是否是给定类的实例
|
||||||
* <pre class="code">
|
* <pre class="code">
|
||||||
@ -743,6 +760,9 @@ public class Assert {
|
|||||||
throw new IllegalArgumentException(StrUtil.format(errorMsgTemplate, params));
|
throw new IllegalArgumentException(StrUtil.format(errorMsgTemplate, params));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region ----- state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查boolean表达式,当检查结果为false时抛出 {@code IllegalStateException}。
|
* 检查boolean表达式,当检查结果为false时抛出 {@code IllegalStateException}。
|
||||||
@ -793,7 +813,9 @@ public class Assert {
|
|||||||
public static void state(final boolean expression) throws IllegalStateException {
|
public static void state(final boolean expression) throws IllegalStateException {
|
||||||
state(expression, "[Assertion failed] - this state invariant must be true");
|
state(expression, "[Assertion failed] - this state invariant must be true");
|
||||||
}
|
}
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region ----- checkIndex
|
||||||
/**
|
/**
|
||||||
* 检查下标(数组、集合、字符串)是否符合要求,下标必须满足:
|
* 检查下标(数组、集合、字符串)是否符合要求,下标必须满足:
|
||||||
*
|
*
|
||||||
@ -834,6 +856,9 @@ public class Assert {
|
|||||||
}
|
}
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region ----- checkBetween
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查值是否在指定范围内
|
* 检查值是否在指定范围内
|
||||||
@ -1001,6 +1026,10 @@ public class Assert {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region ----- equals and notEquals
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 断言两个对象是否不相等,如果两个对象相等 抛出IllegalArgumentException 异常
|
* 断言两个对象是否不相等,如果两个对象相等 抛出IllegalArgumentException 异常
|
||||||
* <pre class="code">
|
* <pre class="code">
|
||||||
@ -1045,7 +1074,6 @@ public class Assert {
|
|||||||
throw errorSupplier.get();
|
throw errorSupplier.get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----------------------------------------------------------------------------------------------------------- Check not equals
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 断言两个对象是否相等,如果两个对象不相等 抛出IllegalArgumentException 异常
|
* 断言两个对象是否相等,如果两个对象不相等 抛出IllegalArgumentException 异常
|
||||||
@ -1091,8 +1119,7 @@ public class Assert {
|
|||||||
throw errorSupplier.get();
|
throw errorSupplier.get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// endregion
|
||||||
// ----------------------------------------------------------------------------------------------------------- Check is equals
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------------------------------------------------------------------------------- Private method start
|
// -------------------------------------------------------------------------------------------------------------------------------------------- Private method start
|
||||||
|
|
||||||
|
@ -40,12 +40,6 @@ public class CompositeConverterTest {
|
|||||||
@Data
|
@Data
|
||||||
public static class EmptyBean {}
|
public static class EmptyBean {}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getConverterTest() {
|
|
||||||
final Converter converter = CompositeConverter.getInstance().getConverter(CharSequence.class, null, false);
|
|
||||||
assertNotNull(converter);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void customTest() {
|
public void customTest() {
|
||||||
final int a = 454553;
|
final int a = 454553;
|
||||||
|
@ -74,8 +74,6 @@ public class JdkHttpConnection implements HeaderOperation<JdkHttpConnection>, Cl
|
|||||||
return new JdkHttpConnection(url, proxy);
|
return new JdkHttpConnection(url, proxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
// region --------------------------------------------------------------- Constructor
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造HttpConnection
|
* 构造HttpConnection
|
||||||
*
|
*
|
||||||
@ -92,9 +90,7 @@ public class JdkHttpConnection implements HeaderOperation<JdkHttpConnection>, Cl
|
|||||||
this.conn.setDoInput(true);
|
this.conn.setDoInput(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// endregion --------------------------------------------------------------- Constructor
|
// region ----- Getters And Setters
|
||||||
|
|
||||||
// region --------------------------------------------------------------- Getters And Setters
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取请求方法,GET/POST
|
* 获取请求方法,GET/POST
|
||||||
@ -279,9 +275,9 @@ public class JdkHttpConnection implements HeaderOperation<JdkHttpConnection>, Cl
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// endregion --------------------------------------------------------------- Getters And Setters
|
// endregion ----- Getters And Setters
|
||||||
|
|
||||||
// region ---------------------------------------------------------------- Headers
|
// region ------ Headers
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置请求头<br>
|
* 设置请求头<br>
|
||||||
@ -327,7 +323,7 @@ public class JdkHttpConnection implements HeaderOperation<JdkHttpConnection>, Cl
|
|||||||
return this.conn.getHeaderFields();
|
return this.conn.getHeaderFields();
|
||||||
}
|
}
|
||||||
|
|
||||||
// endregion---------------------------------------------------------------- Headers
|
// endregion------ Headers
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 连接
|
* 连接
|
||||||
|
@ -29,6 +29,7 @@ import org.dromara.hutool.core.reflect.TypeReference;
|
|||||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||||
import org.dromara.hutool.core.reflect.kotlin.KClassUtil;
|
import org.dromara.hutool.core.reflect.kotlin.KClassUtil;
|
||||||
import org.dromara.hutool.core.text.StrUtil;
|
import org.dromara.hutool.core.text.StrUtil;
|
||||||
|
import org.dromara.hutool.core.util.ObjUtil;
|
||||||
import org.dromara.hutool.json.*;
|
import org.dromara.hutool.json.*;
|
||||||
import org.dromara.hutool.json.reader.JSONParser;
|
import org.dromara.hutool.json.reader.JSONParser;
|
||||||
import org.dromara.hutool.json.reader.JSONTokener;
|
import org.dromara.hutool.json.reader.JSONTokener;
|
||||||
@ -59,13 +60,6 @@ public class JSONConverter implements Converter, Serializable {
|
|||||||
*/
|
*/
|
||||||
public static final JSONConverter INSTANCE = new JSONConverter(null);
|
public static final JSONConverter INSTANCE = new JSONConverter(null);
|
||||||
|
|
||||||
static {
|
|
||||||
final RegisterConverter converter = RegisterConverter.getInstance();
|
|
||||||
converter.register(JSONObject.class, INSTANCE);
|
|
||||||
converter.register(JSONArray.class, INSTANCE);
|
|
||||||
converter.register(JSONPrimitive.class, INSTANCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建JSON转换器
|
* 创建JSON转换器
|
||||||
*
|
*
|
||||||
@ -73,17 +67,25 @@ public class JSONConverter implements Converter, Serializable {
|
|||||||
* @return JSONConverter
|
* @return JSONConverter
|
||||||
*/
|
*/
|
||||||
public static JSONConverter of(final JSONConfig config) {
|
public static JSONConverter of(final JSONConfig config) {
|
||||||
return new JSONConverter(config);
|
final JSONConverter jsonConverter = new JSONConverter(config);
|
||||||
|
jsonConverter.registerConverter = new RegisterConverter(jsonConverter)
|
||||||
|
.register(JSONObject.class, INSTANCE)
|
||||||
|
.register(JSONArray.class, INSTANCE)
|
||||||
|
.register(JSONPrimitive.class, INSTANCE);
|
||||||
|
jsonConverter.specialConverter = new SpecialConverter(jsonConverter);
|
||||||
|
return jsonConverter;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final JSONConfig config;
|
private final JSONConfig config;
|
||||||
|
private RegisterConverter registerConverter;
|
||||||
|
private SpecialConverter specialConverter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造
|
* 构造
|
||||||
*
|
*
|
||||||
* @param config JSON配置
|
* @param config JSON配置
|
||||||
*/
|
*/
|
||||||
public JSONConverter(final JSONConfig config) {
|
private JSONConverter(final JSONConfig config) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,7 +152,7 @@ public class JSONConverter implements Converter, Serializable {
|
|||||||
obj = ((Opt<?>) obj).getOrNull();
|
obj = ((Opt<?>) obj).getOrNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(obj instanceof JSON){
|
if (obj instanceof JSON) {
|
||||||
return (JSON) obj;
|
return (JSON) obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,33 +244,41 @@ public class JSONConverter implements Converter, Serializable {
|
|||||||
|
|
||||||
final Object value;
|
final Object value;
|
||||||
// JSON原始类型
|
// JSON原始类型
|
||||||
if(json instanceof JSONPrimitive){
|
if (json instanceof JSONPrimitive) {
|
||||||
value = ((JSONPrimitive) json).getValue();
|
value = ((JSONPrimitive) json).getValue();
|
||||||
} else {
|
} else {
|
||||||
value = json;
|
value = json;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 标准转换器
|
final JSONConfig config = ObjUtil.defaultIfNull(json.config(), JSONConfig::of);
|
||||||
final Converter converter = RegisterConverter.getInstance().getConverter(targetType, value, true);
|
final boolean ignoreError = config.isIgnoreError();
|
||||||
if (null != converter) {
|
try {
|
||||||
return (T) converter.convert(targetType, value);
|
// 标准转换器
|
||||||
}
|
final Converter converter = registerConverter.getConverter(targetType, value, true);
|
||||||
|
if (null != converter) {
|
||||||
|
return (T) converter.convert(targetType, value);
|
||||||
|
}
|
||||||
|
|
||||||
// 特殊类型转换,包括Collection、Map、强转、Array等
|
// 特殊类型转换,包括Collection、Map、强转、Array等
|
||||||
final T result = (T) SpecialConverter.getInstance().convert(targetType, rawType, value);
|
final T result = (T) specialConverter.convert(targetType, rawType, value);
|
||||||
if (null != result) {
|
if (null != result) {
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
} catch (final ConvertException e) {
|
||||||
|
if (ignoreError) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 尝试转Bean
|
// 尝试转Bean
|
||||||
if (BeanUtil.isWritableBean(rawType)) {
|
if (BeanUtil.isWritableBean(rawType)) {
|
||||||
return BeanCopier.of(value,
|
return BeanCopier.of(value,
|
||||||
ConstructorUtil.newInstanceIfPossible(rawType), targetType,
|
ConstructorUtil.newInstanceIfPossible(rawType), targetType,
|
||||||
InternalJSONUtil.toCopyOptions(json.config())).copy();
|
InternalJSONUtil.toCopyOptions(config)).copy();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 跳过异常时返回null
|
// 跳过异常时返回null
|
||||||
if (json.config().isIgnoreError()) {
|
if (ignoreError) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,28 +16,41 @@
|
|||||||
|
|
||||||
package org.dromara.hutool.json;
|
package org.dromara.hutool.json;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
import org.dromara.hutool.core.io.resource.ResourceUtil;
|
import org.dromara.hutool.core.io.resource.ResourceUtil;
|
||||||
import org.dromara.hutool.core.lang.Console;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.dromara.hutool.json.test.bean.ResultBean;
|
|
||||||
import org.junit.jupiter.api.Disabled;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 测试在bean转换时使用BeanConverter,默认忽略转换失败的字段。
|
* 转换失败,则在设置setIgnoreError(true)不报错
|
||||||
* 现阶段Converter的问题在于,无法更细粒度的控制转换失败的范围,例如Bean的一个字段为List,
|
|
||||||
* list任意一个item转换失败都会导致这个list为null。
|
|
||||||
* <p>
|
|
||||||
* TODO 需要在Converter中添加ConvertOption,用于更细粒度的控制转换规则
|
|
||||||
*/
|
*/
|
||||||
public class Issue1200Test {
|
public class Issue1200Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Disabled
|
public void toBeanTest() {
|
||||||
public void toBeanTest(){
|
final JSONObject jsonObject = JSONUtil.parseObj(
|
||||||
final JSONObject jsonObject = JSONUtil.parseObj(ResourceUtil.readUtf8Str("issue1200.json"));
|
ResourceUtil.readUtf8Str("issue1200.json"),
|
||||||
Console.log(jsonObject);
|
JSONConfig.of().setIgnoreError(true));
|
||||||
|
|
||||||
final ResultBean resultBean = jsonObject.toBean(ResultBean.class);
|
final ResultBean resultBean = jsonObject.toBean(ResultBean.class);
|
||||||
Console.log(resultBean);
|
Assertions.assertNull(resultBean.getItems().get(0).get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
static
|
||||||
|
class ResultBean {
|
||||||
|
public List<List<List<ResultBean.ItemsBean>>> items;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class ItemsBean {
|
||||||
|
public ResultBean.ItemsBean.DetailBean detail;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class DetailBean {
|
||||||
|
public String visitorStatus;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -193,7 +193,7 @@ public class JSONArrayTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void toListWithErrorTest() {
|
public void toListWithErrorTest() {
|
||||||
Assertions.assertThrows(ConvertException.class, ()->{
|
Assertions.assertThrows(JSONException.class, ()->{
|
||||||
final String json = "[['aaa',{'akey':'avalue','bkey':'bvalue'}]]";
|
final String json = "[['aaa',{'akey':'avalue','bkey':'bvalue'}]]";
|
||||||
final JSONArray ja = JSONUtil.parseArray(json);
|
final JSONArray ja = JSONUtil.parseArray(json);
|
||||||
|
|
||||||
|
@ -1,36 +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.json.test.bean;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class ResultBean {
|
|
||||||
public List<List<List<ItemsBean>>> items;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public static class ItemsBean {
|
|
||||||
public DetailBean detail;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public static class DetailBean {
|
|
||||||
public String visitorStatus;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user