修复JWT自定义时间格式后的时间戳转换问题

This commit is contained in:
Looly 2023-03-03 23:26:59 +08:00
parent 2cdce52d4a
commit 3dfdd86ca0
11 changed files with 101 additions and 15 deletions

View File

@ -24,6 +24,7 @@
* 【core 】 修复isXXX转换时的匹配问题issue#I6H0XF@Gitee * 【core 】 修复isXXX转换时的匹配问题issue#I6H0XF@Gitee
* 【core 】 修复MutableObj.equals空指针问题 * 【core 】 修复MutableObj.equals空指针问题
* 【core 】 修复JavaSourceFileObject在编译错误时抛出IOException异常而非CompilerException问题pr#2942@Github * 【core 】 修复JavaSourceFileObject在编译错误时抛出IOException异常而非CompilerException问题pr#2942@Github
* 【jwt 】 修复JWT自定义时间格式后的时间戳转换问题issue#I6IS5B@Gitee
------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------

View File

@ -38,6 +38,7 @@ import cn.hutool.core.lang.Opt;
import cn.hutool.core.lang.TypeReference; import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.map.SafeConcurrentHashMap; import cn.hutool.core.map.SafeConcurrentHashMap;
import cn.hutool.core.util.ClassUtil; import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil; import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.ServiceLoaderUtil; import cn.hutool.core.util.ServiceLoaderUtil;
@ -255,6 +256,11 @@ public class ConverterRegistry implements Serializable {
type = ((TypeReference<?>) type).getType(); type = ((TypeReference<?>) type).getType();
} }
// 自定义对象转换
if(value instanceof TypeConverter){
return ObjUtil.defaultIfNull((T) ((TypeConverter) value).convert(type, value), defaultValue);
}
// 标准转换器 // 标准转换器
final Converter<T> converter = getConverter(type, isCustomFirst); final Converter<T> converter = getConverter(type, isCustomFirst);
if (null != converter) { if (null != converter) {

View File

@ -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<? extends Date>) 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();
}
}

View File

@ -101,10 +101,8 @@ public class TemporalAccessorConverter extends AbstractConverter<TemporalAccesso
@Override @Override
protected TemporalAccessor convertInternal(Object value) { protected TemporalAccessor convertInternal(Object value) {
if (value instanceof Long) { if (value instanceof Number) {
return parseFromLong((Long) value); return parseFromLong(((Number) value).longValue());
} else if (value instanceof Integer) {
return parseFromLong((long) (Integer) value);
} else if (value instanceof TemporalAccessor) { } else if (value instanceof TemporalAccessor) {
return parseFromTemporalAccessor((TemporalAccessor) value); return parseFromTemporalAccessor((TemporalAccessor) value);
} else if (value instanceof Date) { } else if (value instanceof Date) {

View File

@ -177,7 +177,7 @@ public interface JSON extends Cloneable, Serializable {
* @since 3.0.8 * @since 3.0.8
*/ */
default <T> T toBean(Type type) { default <T> 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 是否忽略转换错误 * @param ignoreError 是否忽略转换错误
* @return 实体类对象 * @return 实体类对象
* @since 4.3.2 * @since 4.3.2
* @deprecated 请使用 {@link #toBean(Type)}, ignoreError在JSONConfig中生效
*/ */
@Deprecated
default <T> T toBean(Type type, boolean ignoreError) { default <T> T toBean(Type type, boolean ignoreError) {
return JSONConverter.jsonConvert(type, this, ignoreError); return JSONConverter.jsonConvert(type, this, JSONConfig.create().setIgnoreError(ignoreError));
} }
} }

View File

@ -214,7 +214,7 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
@Override @Override
public <T> T getByPath(String expression, Class<T> resultType) { public <T> T getByPath(String expression, Class<T> resultType) {
return JSONConverter.jsonConvert(resultType, getByPath(expression), true); return JSONConverter.jsonConvert(resultType, getByPath(expression), getConfig());
} }
@Override @Override

View File

@ -65,12 +65,12 @@ public class JSONConverter implements Converter<JSON> {
* @param <T> 转换后的对象类型 * @param <T> 转换后的对象类型
* @param targetType 目标类型 * @param targetType 目标类型
* @param value * @param value
* @param ignoreError 是否忽略转换错误 * @param jsonConfig JSON配置
* @return 目标类型的值 * @return 目标类型的值
* @throws ConvertException 转换失败 * @throws ConvertException 转换失败
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected static <T> T jsonConvert(Type targetType, Object value, boolean ignoreError) throws ConvertException { protected static <T> T jsonConvert(Type targetType, Object value, JSONConfig jsonConfig) throws ConvertException {
if (JSONUtil.isNull(value)) { if (JSONUtil.isNull(value)) {
return null; return null;
} }
@ -92,7 +92,7 @@ public class JSONConverter implements Converter<JSON> {
} }
} }
return jsonToBean(targetType, value, ignoreError); return jsonToBean(targetType, value, jsonConfig.isIgnoreError());
} }
/** /**

View File

@ -2,6 +2,7 @@ package cn.hutool.json;
import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.Convert;
import cn.hutool.core.convert.ConvertException; import cn.hutool.core.convert.ConvertException;
import cn.hutool.core.convert.NumberWithFormat;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil; import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.getter.OptNullBasicTypeFromObjectGetter; import cn.hutool.core.getter.OptNullBasicTypeFromObjectGetter;
@ -138,6 +139,8 @@ public interface JSONGetter<K> extends OptNullBasicTypeFromObjectGetter<K> {
} }
if (obj instanceof Date) { if (obj instanceof Date) {
return (Date) obj; return (Date) obj;
} else if(obj instanceof NumberWithFormat){
return (Date) ((NumberWithFormat) obj).convert(Date.class, obj);
} }
final Optional<String> formatOps = Optional.ofNullable(getConfig()).map(JSONConfig::getDateFormat); final Optional<String> formatOps = Optional.ofNullable(getConfig()).map(JSONConfig::getDateFormat);
@ -232,6 +235,6 @@ public interface JSONGetter<K> extends OptNullBasicTypeFromObjectGetter<K> {
if (JSONUtil.isNull(value)) { if (JSONUtil.isNull(value)) {
return null; return null;
} }
return JSONConverter.jsonConvert(type, value, ignoreError); return JSONConverter.jsonConvert(type, value, JSONConfig.create().setIgnoreError(ignoreError));
} }
} }

View File

@ -317,7 +317,7 @@ public class JSONObject extends MapWrapper<String, Object> implements JSON, JSON
@Override @Override
public <T> T getByPath(String expression, Class<T> resultType) { public <T> T getByPath(String expression, Class<T> resultType) {
return JSONConverter.jsonConvert(resultType, getByPath(expression), true); return JSONConverter.jsonConvert(resultType, getByPath(expression), getConfig());
} }
@Override @Override

View File

@ -1,5 +1,6 @@
package cn.hutool.json; package cn.hutool.json;
import cn.hutool.core.convert.NumberWithFormat;
import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.file.FileReader; import cn.hutool.core.io.file.FileReader;
import cn.hutool.core.lang.TypeReference; import cn.hutool.core.lang.TypeReference;
@ -498,6 +499,7 @@ public class JSONUtil {
* @return 实体类对象 * @return 实体类对象
* @since 4.3.2 * @since 4.3.2
*/ */
@SuppressWarnings("deprecation")
public static <T> T toBean(JSON json, Type beanType, boolean ignoreError) { public static <T> T toBean(JSON json, Type beanType, boolean ignoreError) {
if (null == json) { if (null == json) {
return null; return null;
@ -746,7 +748,6 @@ public class JSONUtil {
* @param jsonConfig JSON选项 * @param jsonConfig JSON选项
* @return 包装后的值null表示此值需被忽略 * @return 包装后的值null表示此值需被忽略
*/ */
@SuppressWarnings({"rawtypes", "unchecked"})
public static Object wrap(Object object, JSONConfig jsonConfig) { public static Object wrap(Object object, JSONConfig jsonConfig) {
if (object == null) { if (object == null) {
return jsonConfig.isIgnoreNullValue() ? null : JSONNull.NULL; return jsonConfig.isIgnoreNullValue() ? null : JSONNull.NULL;
@ -758,6 +759,9 @@ public class JSONUtil {
|| object instanceof Number // || object instanceof Number //
|| ObjectUtil.isBasicType(object) // || ObjectUtil.isBasicType(object) //
) { ) {
if(object instanceof Number && null != jsonConfig.getDateFormat()){
return new NumberWithFormat((Number) object, jsonConfig.getDateFormat());
}
return object; return object;
} }

View File

@ -219,14 +219,14 @@ public class JSONObjectTest {
@Test @Test
public void toBeanNullStrTest() { public void toBeanNullStrTest() {
final JSONObject json = JSONUtil.createObj()// final JSONObject json = JSONUtil.createObj(JSONConfig.create().setIgnoreError(true))//
.set("strValue", "null")// .set("strValue", "null")//
.set("intValue", 123)// .set("intValue", 123)//
// 子对象对应"null"字符串如果忽略错误跳过否则抛出转换异常 // 子对象对应"null"字符串如果忽略错误跳过否则抛出转换异常
.set("beanValue", "null")// .set("beanValue", "null")//
.set("list", JSONUtil.createArray().set("a").set("b")); .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"时应被当作字符串处理 // 当JSON中为字符串"null"时应被当作字符串处理
Assert.assertEquals("null", bean.getStrValue()); Assert.assertEquals("null", bean.getStrValue());
// 当JSON中为字符串"null"时Bean中的字段类型不匹配应在ignoreError模式下忽略注入 // 当JSON中为字符串"null"时Bean中的字段类型不匹配应在ignoreError模式下忽略注入