This commit is contained in:
Looly 2022-09-08 01:46:07 +08:00
parent a06c1e65a1
commit bb99d52a87
13 changed files with 190 additions and 54 deletions

View File

@ -98,20 +98,22 @@ public class CompositeConverter extends RegisterConverter {
*/
@SuppressWarnings("unchecked")
public <T> T convert(Type type, final Object value, final T defaultValue, final boolean isCustomFirst) throws ConvertException {
if (TypeUtil.isUnknown(type) && null == defaultValue) {
// 对于用户不指定目标类型的情况返回原值
return (T) value;
}
if (ObjUtil.isNull(value)) {
return defaultValue;
}
if (TypeUtil.isUnknown(type)) {
// 对于用户不指定目标类型的情况返回原值
if(null == defaultValue){
throw new ConvertException("Unsupported convert to unKnow type: {}", type);
return (T) value;
}
type = defaultValue.getClass();
}
// value本身实现了Converter接口直接调用
if(value instanceof Converter){
return ((Converter) value).convert(type, value, defaultValue);
}
if (type instanceof TypeReference) {
type = ((TypeReference<?>) type).getType();
}

View File

@ -57,6 +57,11 @@ public class BeanConverter implements Converter, Serializable {
return null;
}
// value本身实现了Converter接口直接调用
if(value instanceof Converter){
return ((Converter) value).convert(targetType, value);
}
Class<?> targetClass = TypeUtil.getClass(targetType);
Assert.notNull(targetClass, "Target type is not a class!");
@ -79,6 +84,6 @@ public class BeanConverter implements Converter, Serializable {
return SerializeUtil.deserialize((byte[]) value);
}
throw new ConvertException("Unsupported source type: {}", value.getClass());
throw new ConvertException("Unsupported source type: [{}] to [{}]", value.getClass(), targetType);
}
}

View File

@ -67,7 +67,7 @@ public class DateConverter extends AbstractConverter {
return wrap(targetClass, DateUtil.date((TemporalAccessor) value));
} else if (value instanceof Calendar) {
return wrap(targetClass, DateUtil.date((Calendar) value));
} else if (value instanceof Number) {
} else if (null == this.format && value instanceof Number) {
return wrap(targetClass, ((Number) value).longValue());
} else {
// 统一按照字符串处理

View File

@ -1,7 +1,10 @@
package cn.hutool.json;
import cn.hutool.core.bean.BeanPath;
import cn.hutool.core.convert.ConvertException;
import cn.hutool.core.convert.Converter;
import cn.hutool.core.lang.mutable.MutableEntry;
import cn.hutool.json.convert.JSONConverter;
import java.io.Serializable;
import java.io.StringWriter;
@ -14,7 +17,7 @@ import java.util.function.Predicate;
*
* @author Looly
*/
public interface JSON extends Cloneable, Serializable {
public interface JSON extends Converter, Cloneable, Serializable {
/**
* 获取JSON配置
@ -171,6 +174,11 @@ public interface JSON extends Cloneable, Serializable {
*/
@SuppressWarnings("unchecked")
default <T> T toBean(final Type type) {
return (T) getConfig().getConverter().convert(type, this);
return (T) convert(type, this);
}
@Override
default Object convert(Type targetType, Object value) throws ConvertException {
return JSONConverter.of(getConfig()).convert(targetType, value);
}
}

View File

@ -13,7 +13,6 @@ import cn.hutool.json.serialize.JSONWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
@ -231,11 +230,6 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
return this;
}
@Override
public <T> T toBean(final Type type) {
return JSON.super.toBean(type);
}
/**
* 根据给定名列表与其位置对应的值组成JSONObject
*

View File

@ -1,10 +1,17 @@
package cn.hutool.json;
import cn.hutool.core.comparator.CompareUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.convert.Converter;
import cn.hutool.core.convert.impl.DateConverter;
import cn.hutool.core.convert.impl.TemporalAccessorConverter;
import cn.hutool.core.reflect.TypeUtil;
import cn.hutool.core.text.StrUtil;
import java.io.Serializable;
import java.time.temporal.TemporalAccessor;
import java.util.Comparator;
import java.util.Date;
/**
* JSON配置项
@ -50,7 +57,27 @@ public class JSONConfig implements Serializable {
/**
* 自定义的类型转换器用于在序列化反序列化操作中实现对象类型转换
*/
private Converter converter;
private Converter converter = (type, value)->{
final Class<?> rawType = TypeUtil.getClass(type);
if(Date.class.isAssignableFrom(rawType) || TemporalAccessor.class.isAssignableFrom(rawType)){
// 用户指定了日期格式获取日期属性时使用对应格式
final String valueStr = Convert.convertWithCheck(String.class, value, null, isIgnoreError());
if (null == valueStr) {
return null;
}
// 日期转换支持自定义日期格式
final String format = getDateFormat();
if (StrUtil.isNotBlank(format)) {
if (Date.class.isAssignableFrom(rawType)) {
return new DateConverter(format).convert(type, value);
} else {
return new TemporalAccessorConverter(format).convert(type, value);
}
}
}
return Convert.convertWithCheck(type, value, null, isIgnoreError());
};
/**
* 创建默认的配置项

View File

@ -10,7 +10,6 @@ import cn.hutool.json.serialize.JSONWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collection;
@ -150,11 +149,6 @@ public class JSONObject extends MapWrapper<String, Object> implements JSON, JSON
return this;
}
@Override
public <T> T toBean(final Type type) {
return JSON.super.toBean(type);
}
/**
* 将指定KEY列表的值组成新的JSONArray
*

View File

@ -1,6 +1,6 @@
package cn.hutool.json;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.BeanCopier;
import cn.hutool.json.serialize.JSONDeserializer;
import cn.hutool.json.serialize.JSONString;
@ -28,8 +28,9 @@ public class JSONSupport implements JSONString, JSONDeserializer<Object> {
*/
@Override
public Object deserialize(final JSON json) {
// TODO 经过两次转换效率差待优化
BeanUtil.copyProperties(json.toBean(getClass()), this);
BeanCopier.of(json,
this, this.getClass(),
InternalJSONUtil.toCopyOptions(json.getConfig())).copy();
return this;
}

View File

@ -141,7 +141,7 @@ public class JSONUtil {
* @return JSON
*/
public static JSON parse(final Object obj) {
return JSONConverter.INSTANCE.convert(obj);
return JSONConverter.INSTANCE.toJSON(obj);
}
/**
@ -159,7 +159,7 @@ public class JSONUtil {
* @since 5.3.1
*/
public static JSON parse(final Object obj, final JSONConfig config) {
return JSONConverter.of(config).convert(obj);
return JSONConverter.of(config).toJSON(obj);
}
/**

View File

@ -1,16 +0,0 @@
package cn.hutool.json.convert;
import cn.hutool.core.convert.CompositeConverter;
import cn.hutool.core.convert.ConvertException;
import java.lang.reflect.Type;
public class JSONCompositeConverter extends CompositeConverter {
public static final JSONCompositeConverter INSTANCE = new JSONCompositeConverter();
@Override
public <T> T convert(final Type type, final Object value, final T defaultValue, final boolean isCustomFirst) throws ConvertException {
return super.convert(type, value, defaultValue, isCustomFirst);
}
}

View File

@ -1,18 +1,32 @@
package cn.hutool.json.convert;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.BeanCopier;
import cn.hutool.core.convert.ConvertException;
import cn.hutool.core.convert.Converter;
import cn.hutool.core.convert.impl.ArrayConverter;
import cn.hutool.core.convert.impl.CollectionConverter;
import cn.hutool.core.convert.impl.MapConverter;
import cn.hutool.core.map.MapWrapper;
import cn.hutool.core.reflect.ConstructorUtil;
import cn.hutool.core.reflect.TypeReference;
import cn.hutool.core.reflect.TypeUtil;
import cn.hutool.core.text.StrUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.json.InternalJSONUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONException;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.json.serialize.GlobalSerializeMapping;
import cn.hutool.json.serialize.JSONDeserializer;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
/**
* JSON转换器实现Object对象转换为{@link JSON}支持的对象
@ -49,6 +63,30 @@ public class JSONConverter implements Converter {
this.config = config;
}
@Override
public Object convert(Type targetType, final Object obj) throws ConvertException {
if (null == obj) {
return null;
}
// 对象转JSON
if (targetType instanceof JSON) {
return toJSON(obj);
}
// JSON转对象
if (obj instanceof JSON) {
if (targetType instanceof TypeReference) {
targetType = ((TypeReference<?>) targetType).getType();
}
return toBean(targetType, (JSON) obj);
}
// 无法转换
throw new JSONException("Can not convert from {}: [{}] to [{}]",
obj.getClass().getName(), obj, targetType.getTypeName());
}
/**
* 实现Object对象转换为{@link JSON}支持的对象
* <ul>
@ -59,17 +97,9 @@ public class JSONConverter implements Converter {
*
* @param obj 被转换的对象
* @return 转换后的对象
* @throws ConvertException 转换异常
* @throws JSONException 转换异常
*/
public JSON convert(final Object obj) throws ConvertException {
return (JSON) convert(null, obj);
}
@Override
public Object convert(final Type targetType, final Object obj) throws ConvertException {
if (null == obj) {
return null;
}
public JSON toJSON(final Object obj) throws JSONException {
final JSON json;
if (obj instanceof JSON) {
json = (JSON) obj;
@ -87,4 +117,93 @@ public class JSONConverter implements Converter {
return json;
}
@SuppressWarnings("unchecked")
private <T> T toBean(final Type targetType, final JSON json) {
final Class<T> rawType = (Class<T>) TypeUtil.getClass(targetType);
if(null != rawType && JSONDeserializer.class.isAssignableFrom(rawType)){
return (T) JSONDeserializerConverter.INSTANCE.convert(targetType, json);
}
// 全局自定义反序列化优先级低于实现JSONDeserializer接口
final JSONDeserializer<?> deserializer = GlobalSerializeMapping.getDeserializer(targetType);
if (null != deserializer) {
return (T) deserializer.deserialize(json);
}
// 其他转换不支持非Class的泛型类型
if (null == rawType) {
throw new JSONException("Can not get class from type: {}", targetType);
}
// 特殊类型转换包括CollectionMap强转Array等
final T result = toSpecial(targetType, rawType, json);
if (null != result) {
return result;
}
// 尝试转Bean
if (BeanUtil.isBean(rawType)) {
return BeanCopier.of(json,
ConstructorUtil.newInstanceIfPossible(rawType), targetType,
InternalJSONUtil.toCopyOptions(json.getConfig())).copy();
}
// 跳过异常时返回null
if(json.getConfig().isIgnoreError()){
return null;
}
// 无法转换
throw new JSONException("Can not convert from {}: [{}] to [{}]",
json.getClass().getName(), json, targetType.getTypeName());
}
// ----------------------------------------------------------- Private method start
/**
* 特殊类型转换<br>
* 包括
*
* <pre>
* Collection
* Map
* 强转无需转换
* 数组
* </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;
}
// 集合转换含有泛型参数不可以默认强转
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);
}
// 默认强转
if (rowType.isInstance(value)) {
return (T) value;
}
// 数组转换
if (rowType.isArray()) {
return (T) ArrayConverter.INSTANCE.convert(type, value);
}
// 表示非需要特殊转换的对象
return null;
}
// ----------------------------------------------------------- Private method end
}

View File

@ -15,6 +15,8 @@ import cn.hutool.json.serialize.JSONDeserializer;
public class JSONDeserializerConverter extends AbstractConverter {
private static final long serialVersionUID = 1L;
public static final JSONDeserializerConverter INSTANCE = new JSONDeserializerConverter();
@Override
protected Object convertInternal(final Class<?> targetClass, final Object value) {
// 自定义反序列化

View File

@ -472,7 +472,7 @@ public class JSONObjectTest {
@Test
public void setDateFormatTest3() {
// 自定义格式为只有秒的时间戳用于JWT
// 自定义格式为只有秒的时间戳用于JWT
final JSONConfig jsonConfig = JSONConfig.of().setDateFormat("#sss");
final Date date = DateUtil.parse("2020-06-05 11:16:11");