From bb99d52a871b73396d7dc359d2e3dec34e17d249 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 8 Sep 2022 01:46:07 +0800 Subject: [PATCH] fix code --- .../core/convert/CompositeConverter.java | 12 +- .../core/convert/impl/BeanConverter.java | 7 +- .../core/convert/impl/DateConverter.java | 2 +- .../src/main/java/cn/hutool/json/JSON.java | 12 +- .../main/java/cn/hutool/json/JSONArray.java | 6 - .../main/java/cn/hutool/json/JSONConfig.java | 29 +++- .../main/java/cn/hutool/json/JSONObject.java | 6 - .../main/java/cn/hutool/json/JSONSupport.java | 7 +- .../main/java/cn/hutool/json/JSONUtil.java | 4 +- .../json/convert/JSONCompositeConverter.java | 16 -- .../cn/hutool/json/convert/JSONConverter.java | 139 ++++++++++++++++-- .../convert/JSONDeserializerConverter.java | 2 + .../java/cn/hutool/json/JSONObjectTest.java | 2 +- 13 files changed, 190 insertions(+), 54 deletions(-) delete mode 100755 hutool-json/src/main/java/cn/hutool/json/convert/JSONCompositeConverter.java diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/CompositeConverter.java b/hutool-core/src/main/java/cn/hutool/core/convert/CompositeConverter.java index 3d017a647..a79415213 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/CompositeConverter.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/CompositeConverter.java @@ -98,20 +98,22 @@ public class CompositeConverter extends RegisterConverter { */ @SuppressWarnings("unchecked") public 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(); } diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/impl/BeanConverter.java b/hutool-core/src/main/java/cn/hutool/core/convert/impl/BeanConverter.java index 379afe302..324843a4b 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/impl/BeanConverter.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/impl/BeanConverter.java @@ -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); } } diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/impl/DateConverter.java b/hutool-core/src/main/java/cn/hutool/core/convert/impl/DateConverter.java index be6635a7a..a8b67a2d0 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/impl/DateConverter.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/impl/DateConverter.java @@ -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 { // 统一按照字符串处理 diff --git a/hutool-json/src/main/java/cn/hutool/json/JSON.java b/hutool-json/src/main/java/cn/hutool/json/JSON.java index c0c1f3a7c..134cc98b1 100755 --- a/hutool-json/src/main/java/cn/hutool/json/JSON.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSON.java @@ -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 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); } } diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONArray.java b/hutool-json/src/main/java/cn/hutool/json/JSONArray.java index c8ca774b3..a06d61190 100755 --- a/hutool-json/src/main/java/cn/hutool/json/JSONArray.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONArray.java @@ -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, List, Rando return this; } - @Override - public T toBean(final Type type) { - return JSON.super.toBean(type); - } - /** * 根据给定名列表,与其位置对应的值组成JSONObject * diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONConfig.java b/hutool-json/src/main/java/cn/hutool/json/JSONConfig.java index 2e2526b82..bb2a36c5d 100755 --- a/hutool-json/src/main/java/cn/hutool/json/JSONConfig.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONConfig.java @@ -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()); + }; /** * 创建默认的配置项 diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONObject.java b/hutool-json/src/main/java/cn/hutool/json/JSONObject.java index 645a41d60..6179a5d1c 100755 --- a/hutool-json/src/main/java/cn/hutool/json/JSONObject.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONObject.java @@ -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 implements JSON, JSON return this; } - @Override - public T toBean(final Type type) { - return JSON.super.toBean(type); - } - /** * 将指定KEY列表的值组成新的JSONArray * diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONSupport.java b/hutool-json/src/main/java/cn/hutool/json/JSONSupport.java index 2e170d320..2f6ea18a2 100644 --- a/hutool-json/src/main/java/cn/hutool/json/JSONSupport.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONSupport.java @@ -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 { */ @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; } diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONUtil.java b/hutool-json/src/main/java/cn/hutool/json/JSONUtil.java index 28a38f2be..4f52ded37 100755 --- a/hutool-json/src/main/java/cn/hutool/json/JSONUtil.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONUtil.java @@ -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); } /** diff --git a/hutool-json/src/main/java/cn/hutool/json/convert/JSONCompositeConverter.java b/hutool-json/src/main/java/cn/hutool/json/convert/JSONCompositeConverter.java deleted file mode 100755 index 709899b03..000000000 --- a/hutool-json/src/main/java/cn/hutool/json/convert/JSONCompositeConverter.java +++ /dev/null @@ -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 convert(final Type type, final Object value, final T defaultValue, final boolean isCustomFirst) throws ConvertException { - return super.convert(type, value, defaultValue, isCustomFirst); - } -} diff --git a/hutool-json/src/main/java/cn/hutool/json/convert/JSONConverter.java b/hutool-json/src/main/java/cn/hutool/json/convert/JSONConverter.java index 8422c42b7..03e078204 100644 --- a/hutool-json/src/main/java/cn/hutool/json/convert/JSONConverter.java +++ b/hutool-json/src/main/java/cn/hutool/json/convert/JSONConverter.java @@ -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},支持的对象: *
    @@ -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 toBean(final Type targetType, final JSON json) { + final Class rawType = (Class) 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); + } + // 特殊类型转换,包括Collection、Map、强转、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 + + /** + * 特殊类型转换
    + * 包括: + * + *
    +	 * Collection
    +	 * Map
    +	 * 强转(无需转换)
    +	 * 数组
    +	 * 
    + * + * @param 转换的目标类型(转换器转换到的类型) + * @param type 类型 + * @param value 值 + * @return 转换后的值 + */ + @SuppressWarnings("unchecked") + private T toSpecial(final Type type, final Class 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 } diff --git a/hutool-json/src/main/java/cn/hutool/json/convert/JSONDeserializerConverter.java b/hutool-json/src/main/java/cn/hutool/json/convert/JSONDeserializerConverter.java index c23e8799a..cd7c92d35 100644 --- a/hutool-json/src/main/java/cn/hutool/json/convert/JSONDeserializerConverter.java +++ b/hutool-json/src/main/java/cn/hutool/json/convert/JSONDeserializerConverter.java @@ -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) { // 自定义反序列化 diff --git a/hutool-json/src/test/java/cn/hutool/json/JSONObjectTest.java b/hutool-json/src/test/java/cn/hutool/json/JSONObjectTest.java index 709801136..283e05303 100755 --- a/hutool-json/src/test/java/cn/hutool/json/JSONObjectTest.java +++ b/hutool-json/src/test/java/cn/hutool/json/JSONObjectTest.java @@ -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");