This commit is contained in:
Looly
2024-08-23 12:06:06 +08:00
parent 3ddad8ff6c
commit e185097ce9
27 changed files with 560 additions and 289 deletions

View File

@@ -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();

View File

@@ -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);
}
}