diff --git a/CHANGELOG.md b/CHANGELOG.md index cb5b5e6bd..b7dd43366 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ * 【core 】 修复isXXX转换时的匹配问题(issue#I6H0XF@Gitee) * 【core 】 修复MutableObj.equals空指针问题 * 【core 】 修复JavaSourceFileObject在编译错误时抛出IOException异常而非CompilerException问题(pr#2942@Github) +* 【jwt 】 修复JWT自定义时间格式后的时间戳转换问题(issue#I6IS5B@Gitee) ------------------------------------------------------------------------------------------------------------- diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/ConverterRegistry.java b/hutool-core/src/main/java/cn/hutool/core/convert/ConverterRegistry.java index 86baf507a..3bb96bf87 100755 --- a/hutool-core/src/main/java/cn/hutool/core/convert/ConverterRegistry.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/ConverterRegistry.java @@ -38,6 +38,7 @@ import cn.hutool.core.lang.Opt; import cn.hutool.core.lang.TypeReference; import cn.hutool.core.map.SafeConcurrentHashMap; import cn.hutool.core.util.ClassUtil; +import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ReflectUtil; import cn.hutool.core.util.ServiceLoaderUtil; @@ -255,6 +256,11 @@ public class ConverterRegistry implements Serializable { type = ((TypeReference) type).getType(); } + // 自定义对象转换 + if(value instanceof TypeConverter){ + return ObjUtil.defaultIfNull((T) ((TypeConverter) value).convert(type, value), defaultValue); + } + // 标准转换器 final Converter converter = getConverter(type, isCustomFirst); if (null != converter) { diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/NumberWithFormat.java b/hutool-core/src/main/java/cn/hutool/core/convert/NumberWithFormat.java new file mode 100644 index 000000000..e6cc8101d --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/convert/NumberWithFormat.java @@ -0,0 +1,72 @@ +package cn.hutool.core.convert; + +import cn.hutool.core.convert.impl.DateConverter; +import cn.hutool.core.convert.impl.TemporalAccessorConverter; + +import java.lang.reflect.Type; +import java.time.temporal.TemporalAccessor; +import java.util.Date; + +/** + * 包含格式的数字转换器,主要针对带格式的时间戳 + * + * @author looly + * @since 5.8.13 + */ +public class NumberWithFormat extends Number implements TypeConverter{ + + private final Number number; + private final String format; + + /** + * 构造 + * @param number 数字 + * @param format 格式 + */ + public NumberWithFormat(final Number number, final String format) { + this.number = number; + this.format = format; + } + + @SuppressWarnings("unchecked") + @Override + public Object convert(Type targetType, Object value) { + if (targetType instanceof Class) { + final Class clazz = (Class) targetType; + // https://gitee.com/dromara/hutool/issues/I6IS5B + if (Date.class.isAssignableFrom(clazz)) { + return new DateConverter((Class) clazz, format).convert(this.number, null); + } else if (TemporalAccessor.class.isAssignableFrom(clazz)) { + return new TemporalAccessorConverter(clazz, format).convert(this.number, null); + } else if(String.class == clazz){ + return toString(); + } + } + throw new ConvertException("Unsupported target type {}", targetType); + } + + @Override + public int intValue() { + return this.number.intValue(); + } + + @Override + public long longValue() { + return this.number.longValue(); + } + + @Override + public float floatValue() { + return this.number.floatValue(); + } + + @Override + public double doubleValue() { + return this.number.doubleValue(); + } + + @Override + public String toString() { + return this.number.toString(); + } +} 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 fbb0b9b61..55a0d2ff9 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 @@ -101,10 +101,8 @@ public class TemporalAccessorConverter extends AbstractConverter T toBean(Type type) { - return toBean(type, getConfig().isIgnoreError()); + return JSONConverter.jsonConvert(type, this, getConfig()); } /** @@ -188,8 +188,10 @@ public interface JSON extends Cloneable, Serializable { * @param ignoreError 是否忽略转换错误 * @return 实体类对象 * @since 4.3.2 + * @deprecated 请使用 {@link #toBean(Type)}, ignoreError在JSONConfig中生效 */ + @Deprecated default T toBean(Type type, boolean ignoreError) { - return JSONConverter.jsonConvert(type, this, ignoreError); + return JSONConverter.jsonConvert(type, this, JSONConfig.create().setIgnoreError(ignoreError)); } } 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 881deba19..a97bedd83 100755 --- a/hutool-json/src/main/java/cn/hutool/json/JSONArray.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONArray.java @@ -214,7 +214,7 @@ public class JSONArray implements JSON, JSONGetter, List, Rando @Override public T getByPath(String expression, Class resultType) { - return JSONConverter.jsonConvert(resultType, getByPath(expression), true); + return JSONConverter.jsonConvert(resultType, getByPath(expression), getConfig()); } @Override diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONConverter.java b/hutool-json/src/main/java/cn/hutool/json/JSONConverter.java index a6ef5c2c9..6c79a87ef 100644 --- a/hutool-json/src/main/java/cn/hutool/json/JSONConverter.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONConverter.java @@ -65,12 +65,12 @@ public class JSONConverter implements Converter { * @param 转换后的对象类型 * @param targetType 目标类型 * @param value 值 - * @param ignoreError 是否忽略转换错误 + * @param jsonConfig JSON配置 * @return 目标类型的值 * @throws ConvertException 转换失败 */ @SuppressWarnings("unchecked") - protected static T jsonConvert(Type targetType, Object value, boolean ignoreError) throws ConvertException { + protected static T jsonConvert(Type targetType, Object value, JSONConfig jsonConfig) throws ConvertException { if (JSONUtil.isNull(value)) { return null; } @@ -92,7 +92,7 @@ public class JSONConverter implements Converter { } } - return jsonToBean(targetType, value, ignoreError); + return jsonToBean(targetType, value, jsonConfig.isIgnoreError()); } /** diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONGetter.java b/hutool-json/src/main/java/cn/hutool/json/JSONGetter.java index b2eb31764..7b703806c 100644 --- a/hutool-json/src/main/java/cn/hutool/json/JSONGetter.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONGetter.java @@ -2,6 +2,7 @@ package cn.hutool.json; import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.ConvertException; +import cn.hutool.core.convert.NumberWithFormat; import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.LocalDateTimeUtil; import cn.hutool.core.getter.OptNullBasicTypeFromObjectGetter; @@ -138,6 +139,8 @@ public interface JSONGetter extends OptNullBasicTypeFromObjectGetter { } if (obj instanceof Date) { return (Date) obj; + } else if(obj instanceof NumberWithFormat){ + return (Date) ((NumberWithFormat) obj).convert(Date.class, obj); } final Optional formatOps = Optional.ofNullable(getConfig()).map(JSONConfig::getDateFormat); @@ -232,6 +235,6 @@ public interface JSONGetter extends OptNullBasicTypeFromObjectGetter { if (JSONUtil.isNull(value)) { return null; } - return JSONConverter.jsonConvert(type, value, ignoreError); + return JSONConverter.jsonConvert(type, value, JSONConfig.create().setIgnoreError(ignoreError)); } } 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 306ef61f8..6e40a55bf 100755 --- a/hutool-json/src/main/java/cn/hutool/json/JSONObject.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONObject.java @@ -317,7 +317,7 @@ public class JSONObject extends MapWrapper implements JSON, JSON @Override public T getByPath(String expression, Class resultType) { - return JSONConverter.jsonConvert(resultType, getByPath(expression), true); + return JSONConverter.jsonConvert(resultType, getByPath(expression), getConfig()); } @Override 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 f16b49bd7..7b025ebe7 100755 --- a/hutool-json/src/main/java/cn/hutool/json/JSONUtil.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONUtil.java @@ -1,5 +1,6 @@ package cn.hutool.json; +import cn.hutool.core.convert.NumberWithFormat; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.file.FileReader; import cn.hutool.core.lang.TypeReference; @@ -498,6 +499,7 @@ public class JSONUtil { * @return 实体类对象 * @since 4.3.2 */ + @SuppressWarnings("deprecation") public static T toBean(JSON json, Type beanType, boolean ignoreError) { if (null == json) { return null; @@ -746,7 +748,6 @@ public class JSONUtil { * @param jsonConfig JSON选项 * @return 包装后的值,null表示此值需被忽略 */ - @SuppressWarnings({"rawtypes", "unchecked"}) public static Object wrap(Object object, JSONConfig jsonConfig) { if (object == null) { return jsonConfig.isIgnoreNullValue() ? null : JSONNull.NULL; @@ -758,6 +759,9 @@ public class JSONUtil { || object instanceof Number // || ObjectUtil.isBasicType(object) // ) { + if(object instanceof Number && null != jsonConfig.getDateFormat()){ + return new NumberWithFormat((Number) object, jsonConfig.getDateFormat()); + } return object; } 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 724bb54ac..0a97c2d3d 100755 --- a/hutool-json/src/test/java/cn/hutool/json/JSONObjectTest.java +++ b/hutool-json/src/test/java/cn/hutool/json/JSONObjectTest.java @@ -219,14 +219,14 @@ public class JSONObjectTest { @Test public void toBeanNullStrTest() { - final JSONObject json = JSONUtil.createObj()// + final JSONObject json = JSONUtil.createObj(JSONConfig.create().setIgnoreError(true))// .set("strValue", "null")// .set("intValue", 123)// // 子对象对应"null"字符串,如果忽略错误,跳过,否则抛出转换异常 .set("beanValue", "null")// .set("list", JSONUtil.createArray().set("a").set("b")); - final TestBean bean = json.toBean(TestBean.class, true); + final TestBean bean = json.toBean(TestBean.class); // 当JSON中为字符串"null"时应被当作字符串处理 Assert.assertEquals("null", bean.getStrValue()); // 当JSON中为字符串"null"时Bean中的字段类型不匹配应在ignoreError模式下忽略注入