diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c21fb561..23b69b9b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,8 @@ ### Bug修复 * 【db 】 修复PageResult.isLast计算问题 * 【cron 】 修复更改系统时间后CronTimer被阻塞的问题(issue#838@Github) -* 【db 】 修复Page.addOrder无效问题(issue#838@Github) +* 【db 】 修复Page.addOrder无效问题(issue#I1F9MZ@Gitee) +* 【json 】 修复JSONConvert转换日期空指针问题(issue#I1F8M2@Gitee) ------------------------------------------------------------------------------------------------------------- ## 5.3.1 (2020-04-17) diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/copier/BeanCopier.java b/hutool-core/src/main/java/cn/hutool/core/bean/copier/BeanCopier.java index 80fea3fd4..27ed86fbb 100644 --- a/hutool-core/src/main/java/cn/hutool/core/bean/copier/BeanCopier.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/copier/BeanCopier.java @@ -130,7 +130,10 @@ public class BeanCopier implements Copier, Serializable { * @param bean Bean */ private void mapToBean(Map map, Object bean) { - valueProviderToBean(new MapValueProvider(map, this.copyOptions.ignoreCase), bean); + valueProviderToBean( + new MapValueProvider(map, this.copyOptions.ignoreCase, this.copyOptions.ignoreError), + bean + ); } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/copier/ValueProvider.java b/hutool-core/src/main/java/cn/hutool/core/bean/copier/ValueProvider.java index 6debd127a..d8663a6ce 100644 --- a/hutool-core/src/main/java/cn/hutool/core/bean/copier/ValueProvider.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/copier/ValueProvider.java @@ -18,7 +18,7 @@ public interface ValueProvider{ * 返回值一般需要匹配被注入类型,如果不匹配会调用默认转换 Convert#convert(Type, Object)实现转换 * * @param key Bean对象中参数名 - * @param valueType 被注入的值得类型 + * @param valueType 被注入的值的类型 * @return 对应参数名的值 */ Object value(T key, Type valueType); diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/copier/provider/BeanValueProvider.java b/hutool-core/src/main/java/cn/hutool/core/bean/copier/provider/BeanValueProvider.java index fbc410b2d..e28fe49fa 100644 --- a/hutool-core/src/main/java/cn/hutool/core/bean/copier/provider/BeanValueProvider.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/copier/provider/BeanValueProvider.java @@ -3,6 +3,7 @@ package cn.hutool.core.bean.copier.provider; import cn.hutool.core.bean.BeanDesc.PropDesc; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.copier.ValueProvider; +import cn.hutool.core.convert.Convert; import cn.hutool.core.exceptions.UtilException; import cn.hutool.core.util.StrUtil; @@ -42,20 +43,23 @@ public class BeanValueProvider implements ValueProvider { //boolean类型字段字段名支持两种方式 sourcePd = sourcePdMap.get(StrUtil.upperFirstAndAddPre(key, "is")); } - + + Object result = null; if (null != sourcePd) { final Method getter = sourcePd.getGetter(); if (null != getter) { try { - return getter.invoke(source); + result = getter.invoke(source); } catch (Exception e) { if (false == ignoreError) { throw new UtilException(e, "Inject [{}] error!", key); } } + + result = Convert.convertWithCheck(valueType,result, null, ignoreError); } } - return null; + return result; } @Override diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/copier/provider/MapValueProvider.java b/hutool-core/src/main/java/cn/hutool/core/bean/copier/provider/MapValueProvider.java index 896cfab61..f2dc4a471 100644 --- a/hutool-core/src/main/java/cn/hutool/core/bean/copier/provider/MapValueProvider.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/copier/provider/MapValueProvider.java @@ -17,14 +17,26 @@ import java.util.Map; public class MapValueProvider implements ValueProvider { private final Map map; + private final boolean ignoreError; + + /** + * 构造 + * + * @param map Map + * @param ignoreCase 是否忽略key的大小写 + */ + public MapValueProvider(Map map, boolean ignoreCase) { + this(map, ignoreCase, false); + } /** * 构造 * * @param map Map * @param ignoreCase 是否忽略key的大小写 + * @since 5.3.2 */ - public MapValueProvider(Map map, boolean ignoreCase) { + public MapValueProvider(Map map, boolean ignoreCase, boolean ignoreError) { if(false == ignoreCase || map instanceof CaseInsensitiveMap) { //不忽略大小写或者提供的Map本身为CaseInsensitiveMap则无需转换 this.map = map; @@ -32,6 +44,7 @@ public class MapValueProvider implements ValueProvider { //转换为大小写不敏感的Map this.map = new CaseInsensitiveMap<>(map); } + this.ignoreError = ignoreError; } @Override @@ -42,7 +55,7 @@ public class MapValueProvider implements ValueProvider { value = map.get(StrUtil.toUnderlineCase(key)); } - return Convert.convert(valueType, value); + return Convert.convertWithCheck(valueType, value, null, this.ignoreError); } @Override diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/Convert.java b/hutool-core/src/main/java/cn/hutool/core/convert/Convert.java index d4770dda7..d06fed1e8 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/Convert.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/Convert.java @@ -1,14 +1,5 @@ package cn.hutool.core.convert; -import java.lang.reflect.Type; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.nio.charset.Charset; -import java.time.Instant; -import java.time.LocalDateTime; -import java.util.*; -import java.util.concurrent.TimeUnit; - import cn.hutool.core.convert.impl.CollectionConverter; import cn.hutool.core.convert.impl.EnumConverter; import cn.hutool.core.convert.impl.MapConverter; @@ -20,6 +11,21 @@ import cn.hutool.core.util.ClassUtil; import cn.hutool.core.util.HexUtil; import cn.hutool.core.util.StrUtil; +import java.lang.reflect.Type; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.nio.charset.Charset; +import java.time.Instant; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; + /** * 类型转换器 * @@ -674,7 +680,7 @@ public class Convert { * @throws ConvertException 转换器不存在 */ public static T convert(Type type, Object value, T defaultValue) throws ConvertException { - return ConverterRegistry.getInstance().convert(type, value, defaultValue); + return convertWithCheck(type, value, defaultValue, false); } /** @@ -703,10 +709,30 @@ public class Convert { * @since 4.5.10 */ public static T convertQuietly(Type type, Object value, T defaultValue) { + return convertWithCheck(type, value, defaultValue, true); + } + + /** + * 转换值为指定类型,可选是否不抛异常转换
+ * 当转换失败时返回默认值 + * + * @param 目标类型 + * @param type 目标类型 + * @param value 值 + * @param defaultValue 默认值 + * @param quietly 是否静默转换,true不抛异常 + * @return 转换后的值 + * @since 5.3.2 + */ + public static T convertWithCheck(Type type, Object value, T defaultValue, boolean quietly) { + final ConverterRegistry registry = ConverterRegistry.getInstance(); try { - return convert(type, value, defaultValue); + return registry.convert(type, value, defaultValue); } catch (Exception e) { - return defaultValue; + if(quietly){ + return defaultValue; + } + throw e; } } diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/impl/TemporalAccessorConverter.java b/hutool-core/src/main/java/cn/hutool/core/convert/impl/TemporalAccessorConverter.java index af6331626..02bfe6a22 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/impl/TemporalAccessorConverter.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/impl/TemporalAccessorConverter.java @@ -4,6 +4,7 @@ import cn.hutool.core.convert.AbstractConverter; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; import java.time.Instant; import java.time.LocalDate; @@ -107,6 +108,10 @@ public class TemporalAccessorConverter extends AbstractConverter { } if(value instanceof JSON) { - JSONDeserializer deserializer = GlobalSerializeMapping.getDeserializer(targetType); + final JSONDeserializer deserializer = GlobalSerializeMapping.getDeserializer(targetType); if(null != deserializer) { return (T) deserializer.deserialize((JSON)value); } } - Object targetValue; - try { - targetValue = Convert.convert(targetType, value); - } catch (ConvertException e) { - if (ignoreError) { - return null; - } - throw e; - } - + final T targetValue = ignoreError ? + Convert.convertQuietly(targetType, value): + Convert.convert(targetType, value); + if (null == targetValue && false == ignoreError) { if (StrUtil.isBlankIfStr(value)) { // 对于传入空字符串的情况,如果转换的目标对象是非字符串或非原始类型,转换器会返回false。 @@ -97,7 +91,7 @@ public class JSONConverter implements Converter { throw new ConvertException("Can not convert {} to type {}", value, ObjectUtil.defaultIfNull(TypeUtil.getClass(targetType), targetType)); } - return (T) targetValue; + return targetValue; } @Override diff --git a/hutool-json/src/test/java/cn/hutool/json/IssueI1F8M2.java b/hutool-json/src/test/java/cn/hutool/json/IssueI1F8M2.java new file mode 100644 index 000000000..5f928a337 --- /dev/null +++ b/hutool-json/src/test/java/cn/hutool/json/IssueI1F8M2.java @@ -0,0 +1,38 @@ +package cn.hutool.json; + +import lombok.Data; +import org.junit.Assert; +import org.junit.Test; + +import java.time.LocalDateTime; + +/** + * https://gitee.com/loolly/dashboard/issues?id=I1F8M2 + */ +public class IssueI1F8M2 { + @Test + public void toBeanTest() { + String jsonStr = "{\"eventType\":\"fee\",\"fwdAlertingTime\":\"2020-04-22 16:34:13\",\"fwdAnswerTime\":\"\"}"; + Param param = JSONUtil.toBean(jsonStr, Param.class); + Assert.assertEquals("2020-04-22T16:34:13", param.getFwdAlertingTime().toString()); + Assert.assertNull(param.getFwdAnswerTime()); + } + + // Param类的字段 + @Data + static class Param { + /** + * fee表示话单事件 + */ + private String eventType; + /** + * 转接呼叫后振铃时间 + */ + private LocalDateTime fwdAlertingTime; + /** + * 转接呼叫后应答时间 + */ + private LocalDateTime fwdAnswerTime; + + } +}