mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
fix code
This commit is contained in:
parent
264d24b54c
commit
eec27cdc40
@ -16,8 +16,9 @@
|
|||||||
|
|
||||||
package org.dromara.hutool.core.bean;
|
package org.dromara.hutool.core.bean;
|
||||||
|
|
||||||
|
import org.dromara.hutool.core.reflect.Invoker;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -62,7 +63,7 @@ public interface BeanDesc extends Serializable {
|
|||||||
* @param fieldName 字段名
|
* @param fieldName 字段名
|
||||||
* @return Getter方法
|
* @return Getter方法
|
||||||
*/
|
*/
|
||||||
default Method getGetter(final String fieldName) {
|
default Invoker getGetter(final String fieldName) {
|
||||||
final PropDesc desc = getProp(fieldName);
|
final PropDesc desc = getProp(fieldName);
|
||||||
return null == desc ? null : desc.getGetter();
|
return null == desc ? null : desc.getGetter();
|
||||||
}
|
}
|
||||||
@ -73,7 +74,7 @@ public interface BeanDesc extends Serializable {
|
|||||||
* @param fieldName 字段名
|
* @param fieldName 字段名
|
||||||
* @return Setter方法
|
* @return Setter方法
|
||||||
*/
|
*/
|
||||||
default Method getSetter(final String fieldName) {
|
default Invoker getSetter(final String fieldName) {
|
||||||
final PropDesc desc = getProp(fieldName);
|
final PropDesc desc = getProp(fieldName);
|
||||||
return null == desc ? null : desc.getSetter();
|
return null == desc ? null : desc.getSetter();
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ import org.dromara.hutool.core.annotation.AnnotationUtil;
|
|||||||
import org.dromara.hutool.core.annotation.PropIgnore;
|
import org.dromara.hutool.core.annotation.PropIgnore;
|
||||||
import org.dromara.hutool.core.convert.ConvertUtil;
|
import org.dromara.hutool.core.convert.ConvertUtil;
|
||||||
import org.dromara.hutool.core.reflect.*;
|
import org.dromara.hutool.core.reflect.*;
|
||||||
import org.dromara.hutool.core.reflect.method.MethodUtil;
|
import org.dromara.hutool.core.reflect.method.MethodInvoker;
|
||||||
|
|
||||||
import java.beans.Transient;
|
import java.beans.Transient;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
@ -37,7 +37,7 @@ public class PropDesc {
|
|||||||
/**
|
/**
|
||||||
* 字段
|
* 字段
|
||||||
*/
|
*/
|
||||||
private Field field;
|
private Invoker fieldInvoker;
|
||||||
/**
|
/**
|
||||||
* 字段名
|
* 字段名
|
||||||
*/
|
*/
|
||||||
@ -45,11 +45,11 @@ public class PropDesc {
|
|||||||
/**
|
/**
|
||||||
* Getter方法
|
* Getter方法
|
||||||
*/
|
*/
|
||||||
protected Method getter;
|
protected Invoker getter;
|
||||||
/**
|
/**
|
||||||
* Setter方法
|
* Setter方法
|
||||||
*/
|
*/
|
||||||
protected Method setter;
|
protected Invoker setter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造<br>
|
* 构造<br>
|
||||||
@ -61,7 +61,7 @@ public class PropDesc {
|
|||||||
*/
|
*/
|
||||||
public PropDesc(final Field field, final Method getter, final Method setter) {
|
public PropDesc(final Field field, final Method getter, final Method setter) {
|
||||||
this(FieldUtil.getFieldName(field), getter, setter);
|
this(FieldUtil.getFieldName(field), getter, setter);
|
||||||
this.field = field;
|
this.fieldInvoker = null == field ? null : FieldInvoker.of(field);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -69,13 +69,13 @@ public class PropDesc {
|
|||||||
* Getter和Setter方法设置为默认可访问
|
* Getter和Setter方法设置为默认可访问
|
||||||
*
|
*
|
||||||
* @param fieldName 字段名
|
* @param fieldName 字段名
|
||||||
* @param getter get方法
|
* @param getterMethod get方法
|
||||||
* @param setter set方法
|
* @param setterMethod set方法
|
||||||
*/
|
*/
|
||||||
public PropDesc(final String fieldName, final Method getter, final Method setter) {
|
public PropDesc(final String fieldName, final Method getterMethod, final Method setterMethod) {
|
||||||
this.fieldName = fieldName;
|
this.fieldName = fieldName;
|
||||||
this.getter = ReflectUtil.setAccessible(getter);
|
this.getter = null == getterMethod ? null : MethodInvoker.of(getterMethod);
|
||||||
this.setter = ReflectUtil.setAccessible(setter);
|
this.setter = null == setterMethod ? null : MethodInvoker.of(setterMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -94,7 +94,11 @@ public class PropDesc {
|
|||||||
* @since 5.1.6
|
* @since 5.1.6
|
||||||
*/
|
*/
|
||||||
public String getRawFieldName() {
|
public String getRawFieldName() {
|
||||||
return null == this.field ? null : this.field.getName();
|
if (null == this.fieldInvoker) {
|
||||||
|
return this.fieldName;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.fieldInvoker.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -103,7 +107,10 @@ public class PropDesc {
|
|||||||
* @return 字段
|
* @return 字段
|
||||||
*/
|
*/
|
||||||
public Field getField() {
|
public Field getField() {
|
||||||
return this.field;
|
if (null != this.fieldInvoker && this.fieldInvoker instanceof FieldInvoker) {
|
||||||
|
return ((FieldInvoker) this.fieldInvoker).getField();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -113,8 +120,8 @@ public class PropDesc {
|
|||||||
* @return 字段类型
|
* @return 字段类型
|
||||||
*/
|
*/
|
||||||
public Type getFieldType() {
|
public Type getFieldType() {
|
||||||
if (null != this.field) {
|
if (null != this.fieldInvoker) {
|
||||||
return TypeUtil.getType(this.field);
|
return this.fieldInvoker.getType();
|
||||||
}
|
}
|
||||||
return findPropType(getter, setter);
|
return findPropType(getter, setter);
|
||||||
}
|
}
|
||||||
@ -126,27 +133,27 @@ public class PropDesc {
|
|||||||
* @return 字段类型
|
* @return 字段类型
|
||||||
*/
|
*/
|
||||||
public Class<?> getFieldClass() {
|
public Class<?> getFieldClass() {
|
||||||
if (null != this.field) {
|
if (null != this.fieldInvoker) {
|
||||||
return TypeUtil.getClass(this.field);
|
return this.fieldInvoker.getTypeClass();
|
||||||
}
|
}
|
||||||
return findPropClass(getter, setter);
|
return findPropClass(getter, setter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取Getter方法,可能为{@code null}
|
* 获取Getter方法Invoker,可能为{@code null}
|
||||||
*
|
*
|
||||||
* @return Getter方法
|
* @return Getter方法Invoker
|
||||||
*/
|
*/
|
||||||
public Method getGetter() {
|
public Invoker getGetter() {
|
||||||
return this.getter;
|
return this.getter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取Setter方法,可能为{@code null}
|
* 获取Setter方法Invoker,可能为{@code null}
|
||||||
*
|
*
|
||||||
* @return {@link Method}Setter 方法对象
|
* @return {@link Method}Setter 方法Invoker
|
||||||
*/
|
*/
|
||||||
public Method getSetter() {
|
public Invoker getSetter() {
|
||||||
return this.setter;
|
return this.setter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,18 +165,27 @@ public class PropDesc {
|
|||||||
* @since 5.4.2
|
* @since 5.4.2
|
||||||
*/
|
*/
|
||||||
public boolean isReadable(final boolean checkTransient) {
|
public boolean isReadable(final boolean checkTransient) {
|
||||||
// 检查是否有getter方法或是否为public修饰
|
Field field = null;
|
||||||
if (null == this.getter && !ModifierUtil.isPublic(this.field)) {
|
if (this.fieldInvoker instanceof FieldInvoker) {
|
||||||
return false;
|
field = ((FieldInvoker) this.fieldInvoker).getField();
|
||||||
|
}
|
||||||
|
Method getterMethod = null;
|
||||||
|
if (this.getter instanceof MethodInvoker) {
|
||||||
|
getterMethod = ((MethodInvoker) this.getter).getMethod();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查transient关键字和@Transient注解
|
// 检查transient关键字和@Transient注解
|
||||||
if (checkTransient && isTransientForGet()) {
|
if (checkTransient && isTransientForGet(field, getterMethod)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查@PropIgnore注解
|
// 检查@PropIgnore注解
|
||||||
return !isIgnoreGet();
|
if (isIgnoreGet(field, getterMethod)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否有getter方法或是否为public修饰
|
||||||
|
return null != getterMethod || ModifierUtil.isPublic(field);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -183,11 +199,9 @@ public class PropDesc {
|
|||||||
*/
|
*/
|
||||||
public Object getValue(final Object bean) {
|
public Object getValue(final Object bean) {
|
||||||
if (null != this.getter) {
|
if (null != this.getter) {
|
||||||
// issue#3671 JDK15+ 修改了lambda的策略,动态生成后在metaspace不会释放,导致资源占用高
|
return this.getter.invoke(bean);
|
||||||
//return LambdaUtil.buildGetter(this.getter).apply(bean);
|
} else if (null != this.fieldInvoker) {
|
||||||
return MethodUtil.invoke(bean, this.getter);
|
return fieldInvoker.invoke(bean);
|
||||||
} else if (ModifierUtil.isPublic(this.field)) {
|
|
||||||
return FieldUtil.getFieldValue(bean, this.field);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@ -230,18 +244,27 @@ public class PropDesc {
|
|||||||
* @since 5.4.2
|
* @since 5.4.2
|
||||||
*/
|
*/
|
||||||
public boolean isWritable(final boolean checkTransient) {
|
public boolean isWritable(final boolean checkTransient) {
|
||||||
// 检查是否有getter方法或是否为public修饰
|
Field field = null;
|
||||||
if (null == this.setter && !ModifierUtil.isPublic(this.field)) {
|
if (this.fieldInvoker instanceof FieldInvoker) {
|
||||||
return false;
|
field = ((FieldInvoker) this.fieldInvoker).getField();
|
||||||
|
}
|
||||||
|
Method setterMethod = null;
|
||||||
|
if (this.setter instanceof MethodInvoker) {
|
||||||
|
setterMethod = ((MethodInvoker) this.setter).getMethod();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查transient关键字和@Transient注解
|
// 检查transient关键字和@Transient注解
|
||||||
if (checkTransient && isTransientForSet()) {
|
if (checkTransient && isTransientForSet(field, setterMethod)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查@PropIgnore注解
|
// 检查@PropIgnore注解
|
||||||
return !isIgnoreSet();
|
if(isIgnoreSet(field, setterMethod)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否有setter方法或是否为public修饰
|
||||||
|
return null != setterMethod || ModifierUtil.isPublic(field);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -256,9 +279,9 @@ public class PropDesc {
|
|||||||
*/
|
*/
|
||||||
public PropDesc setValue(final Object bean, final Object value) {
|
public PropDesc setValue(final Object bean, final Object value) {
|
||||||
if (null != this.setter) {
|
if (null != this.setter) {
|
||||||
MethodUtil.invoke(bean, this.setter, value);
|
this.setter.invoke(bean, value);
|
||||||
} else if (ModifierUtil.isPublic(this.field)) {
|
} else if (null != this.fieldInvoker) {
|
||||||
FieldUtil.setFieldValue(bean, this.field, value);
|
fieldInvoker.invoke(bean, value);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -325,29 +348,29 @@ public class PropDesc {
|
|||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "PropDesc{" +
|
return "PropDesc{" +
|
||||||
"field=" + field +
|
"field=" + fieldInvoker +
|
||||||
", fieldName=" + fieldName +
|
", fieldName=" + fieldName +
|
||||||
", getter=" + getter +
|
", getter=" + getter +
|
||||||
", setter=" + setter +
|
", setter=" + setter +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------ Private method start
|
// region ----- private methods
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过Getter和Setter方法中找到属性类型
|
* 通过Getter和Setter方法中找到属性类型
|
||||||
*
|
*
|
||||||
* @param getter Getter方法
|
* @param getterInvoker Getter方法Invoker
|
||||||
* @param setter Setter方法
|
* @param setterInvoker Setter方法Invoker
|
||||||
* @return {@link Type}
|
* @return {@link Type}
|
||||||
*/
|
*/
|
||||||
private Type findPropType(final Method getter, final Method setter) {
|
private Type findPropType(final Invoker getterInvoker, final Invoker setterInvoker) {
|
||||||
Type type = null;
|
Type type = null;
|
||||||
if (null != getter) {
|
if (null != getterInvoker) {
|
||||||
type = TypeUtil.getReturnType(getter);
|
type = getterInvoker.getType();
|
||||||
}
|
}
|
||||||
if (null == type && null != setter) {
|
if (null == type && null != setterInvoker) {
|
||||||
type = TypeUtil.getParamType(setter, 0);
|
type = setterInvoker.getType();
|
||||||
}
|
}
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
@ -355,36 +378,21 @@ public class PropDesc {
|
|||||||
/**
|
/**
|
||||||
* 通过Getter和Setter方法中找到属性类型
|
* 通过Getter和Setter方法中找到属性类型
|
||||||
*
|
*
|
||||||
* @param getter Getter方法
|
* @param getterInvoker Getter方法Invoker
|
||||||
* @param setter Setter方法
|
* @param setterInvoker Setter方法Invoker
|
||||||
* @return {@link Type}
|
* @return {@link Type}
|
||||||
*/
|
*/
|
||||||
private Class<?> findPropClass(final Method getter, final Method setter) {
|
private Class<?> findPropClass(final Invoker getterInvoker, final Invoker setterInvoker) {
|
||||||
Class<?> type = null;
|
Class<?> type = null;
|
||||||
if (null != getter) {
|
if (null != getterInvoker) {
|
||||||
type = TypeUtil.getReturnClass(getter);
|
type = getterInvoker.getTypeClass();
|
||||||
}
|
}
|
||||||
if (null == type && null != setter) {
|
if (null == type && null != setterInvoker) {
|
||||||
type = TypeUtil.getFirstParamClass(setter);
|
type = setterInvoker.getTypeClass();
|
||||||
}
|
}
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查字段是否被忽略写,通过{@link PropIgnore} 注解完成,规则为:
|
|
||||||
* <pre>
|
|
||||||
* 1. 在字段上有{@link PropIgnore} 注解
|
|
||||||
* 2. 在setXXX方法上有{@link PropIgnore} 注解
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @return 是否忽略写
|
|
||||||
* @since 5.4.2
|
|
||||||
*/
|
|
||||||
private boolean isIgnoreSet() {
|
|
||||||
return AnnotationUtil.hasAnnotation(this.field, PropIgnore.class)
|
|
||||||
|| AnnotationUtil.hasAnnotation(this.setter, PropIgnore.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查字段是否被忽略读,通过{@link PropIgnore} 注解完成,规则为:
|
* 检查字段是否被忽略读,通过{@link PropIgnore} 注解完成,规则为:
|
||||||
* <pre>
|
* <pre>
|
||||||
@ -392,30 +400,48 @@ public class PropDesc {
|
|||||||
* 2. 在getXXX方法上有{@link PropIgnore} 注解
|
* 2. 在getXXX方法上有{@link PropIgnore} 注解
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
* @param field 字段,可为{@code null}
|
||||||
|
* @param getterMethod 读取方法,可为{@code null}
|
||||||
* @return 是否忽略读
|
* @return 是否忽略读
|
||||||
* @since 5.4.2
|
|
||||||
*/
|
*/
|
||||||
private boolean isIgnoreGet() {
|
private static boolean isIgnoreGet(final Field field, final Method getterMethod) {
|
||||||
return AnnotationUtil.hasAnnotation(this.field, PropIgnore.class)
|
return AnnotationUtil.hasAnnotation(field, PropIgnore.class)
|
||||||
|| AnnotationUtil.hasAnnotation(this.getter, PropIgnore.class);
|
|| AnnotationUtil.hasAnnotation(getterMethod, PropIgnore.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查字段是否被忽略写,通过{@link PropIgnore} 注解完成,规则为:
|
||||||
|
* <pre>
|
||||||
|
* 1. 在字段上有{@link PropIgnore} 注解
|
||||||
|
* 2. 在setXXX方法上有{@link PropIgnore} 注解
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param field 字段,可为{@code null}
|
||||||
|
* @param setterMethod 写方法,可为{@code null}
|
||||||
|
* @return 是否忽略写
|
||||||
|
*/
|
||||||
|
private static boolean isIgnoreSet(final Field field, final Method setterMethod) {
|
||||||
|
return AnnotationUtil.hasAnnotation(field, PropIgnore.class)
|
||||||
|
|| AnnotationUtil.hasAnnotation(setterMethod, PropIgnore.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 字段和Getter方法是否为Transient关键字修饰的
|
* 字段和Getter方法是否为Transient关键字修饰的
|
||||||
*
|
*
|
||||||
|
* @param field 字段,可为{@code null}
|
||||||
|
* @param getterMethod 读取方法,可为{@code null}
|
||||||
* @return 是否为Transient关键字修饰的
|
* @return 是否为Transient关键字修饰的
|
||||||
* @since 5.3.11
|
|
||||||
*/
|
*/
|
||||||
private boolean isTransientForGet() {
|
private static boolean isTransientForGet(final Field field, final Method getterMethod) {
|
||||||
boolean isTransient = ModifierUtil.hasModifier(this.field, ModifierType.TRANSIENT);
|
boolean isTransient = ModifierUtil.hasModifier(field, ModifierType.TRANSIENT);
|
||||||
|
|
||||||
// 检查Getter方法
|
// 检查Getter方法
|
||||||
if (!isTransient && null != this.getter) {
|
if (!isTransient && null != getterMethod) {
|
||||||
isTransient = ModifierUtil.hasModifier(this.getter, ModifierType.TRANSIENT);
|
isTransient = ModifierUtil.hasModifier(getterMethod, ModifierType.TRANSIENT);
|
||||||
|
|
||||||
// 检查注解
|
// 检查注解
|
||||||
if (!isTransient) {
|
if (!isTransient) {
|
||||||
isTransient = AnnotationUtil.hasAnnotation(this.getter, Transient.class);
|
isTransient = AnnotationUtil.hasAnnotation(getterMethod, Transient.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -425,23 +451,24 @@ public class PropDesc {
|
|||||||
/**
|
/**
|
||||||
* 字段和Getter方法是否为Transient关键字修饰的
|
* 字段和Getter方法是否为Transient关键字修饰的
|
||||||
*
|
*
|
||||||
|
* @param field 字段,可为{@code null}
|
||||||
|
* @param setterMethod 写方法,可为{@code null}
|
||||||
* @return 是否为Transient关键字修饰的
|
* @return 是否为Transient关键字修饰的
|
||||||
* @since 5.3.11
|
|
||||||
*/
|
*/
|
||||||
private boolean isTransientForSet() {
|
private static boolean isTransientForSet(final Field field, final Method setterMethod) {
|
||||||
boolean isTransient = ModifierUtil.hasModifier(this.field, ModifierType.TRANSIENT);
|
boolean isTransient = ModifierUtil.hasModifier(field, ModifierType.TRANSIENT);
|
||||||
|
|
||||||
// 检查Getter方法
|
// 检查Getter方法
|
||||||
if (!isTransient && null != this.setter) {
|
if (!isTransient && null != setterMethod) {
|
||||||
isTransient = ModifierUtil.hasModifier(this.setter, ModifierType.TRANSIENT);
|
isTransient = ModifierUtil.hasModifier(setterMethod, ModifierType.TRANSIENT);
|
||||||
|
|
||||||
// 检查注解
|
// 检查注解
|
||||||
if (!isTransient) {
|
if (!isTransient) {
|
||||||
isTransient = AnnotationUtil.hasAnnotation(this.setter, Transient.class);
|
isTransient = AnnotationUtil.hasAnnotation(setterMethod, Transient.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return isTransient;
|
return isTransient;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------ Private method end
|
// endregion
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
package org.dromara.hutool.core.bean;
|
package org.dromara.hutool.core.bean;
|
||||||
|
|
||||||
import org.dromara.hutool.core.bean.path.AbstractBeanDesc;
|
import org.dromara.hutool.core.bean.path.AbstractBeanDesc;
|
||||||
|
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||||
|
import org.dromara.hutool.core.reflect.method.MethodInvoker;
|
||||||
import org.dromara.hutool.core.reflect.method.MethodNameUtil;
|
import org.dromara.hutool.core.reflect.method.MethodNameUtil;
|
||||||
import org.dromara.hutool.core.reflect.method.MethodUtil;
|
import org.dromara.hutool.core.reflect.method.MethodUtil;
|
||||||
import org.dromara.hutool.core.util.BooleanUtil;
|
import org.dromara.hutool.core.util.BooleanUtil;
|
||||||
@ -86,17 +88,17 @@ public class SimpleBeanDesc extends AbstractBeanDesc {
|
|||||||
} else{
|
} else{
|
||||||
if(isSetter){
|
if(isSetter){
|
||||||
if(null == propDesc.setter ||
|
if(null == propDesc.setter ||
|
||||||
propDesc.setter.getParameterTypes()[0].isAssignableFrom(method.getParameterTypes()[0])){
|
propDesc.setter.getTypeClass().isAssignableFrom(method.getParameterTypes()[0])){
|
||||||
// 如果存在多个重载的setter方法,选择参数类型最匹配的
|
// 如果存在多个重载的setter方法,选择参数类型最匹配的
|
||||||
propDesc.setter = method;
|
propDesc.setter = MethodInvoker.of(method);
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
if(null == propDesc.getter ||
|
if(null == propDesc.getter ||
|
||||||
(BooleanUtil.isBoolean(propDesc.getter.getReturnType()) &&
|
(BooleanUtil.isBoolean(propDesc.getter.getTypeClass()) &&
|
||||||
BooleanUtil.isBoolean(method.getReturnType()) &&
|
BooleanUtil.isBoolean(method.getReturnType()) &&
|
||||||
methodName.startsWith(MethodNameUtil.IS_PREFIX))){
|
methodName.startsWith(MethodNameUtil.IS_PREFIX))){
|
||||||
// 如果返回值为Boolean或boolean,isXXX优先于getXXX
|
// 如果返回值为Boolean或boolean,isXXX优先于getXXX
|
||||||
propDesc.getter = method;
|
propDesc.getter = MethodInvoker.of(method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -259,8 +259,6 @@ public class RegisterConverter implements Converter, Serializable {
|
|||||||
defaultConverterMap.put(AtomicLongArray.class, new AtomicLongArrayConverter());
|
defaultConverterMap.put(AtomicLongArray.class, new AtomicLongArrayConverter());
|
||||||
|
|
||||||
// 其它类型
|
// 其它类型
|
||||||
defaultConverterMap.put(TimeZone.class, new TimeZoneConverter());
|
|
||||||
defaultConverterMap.put(ZoneId.class, new ZoneIdConverter());
|
|
||||||
defaultConverterMap.put(Locale.class, new LocaleConverter());
|
defaultConverterMap.put(Locale.class, new LocaleConverter());
|
||||||
defaultConverterMap.put(Charset.class, new CharsetConverter());
|
defaultConverterMap.put(Charset.class, new CharsetConverter());
|
||||||
defaultConverterMap.put(Path.class, new PathConverter());
|
defaultConverterMap.put(Path.class, new PathConverter());
|
||||||
|
@ -94,6 +94,10 @@ public class SpecialConverter implements Converter, Serializable {
|
|||||||
// // 空值转空Bean
|
// // 空值转空Bean
|
||||||
converterSet.add(EmptyBeanConverter.INSTANCE);
|
converterSet.add(EmptyBeanConverter.INSTANCE);
|
||||||
|
|
||||||
|
// 日期相关
|
||||||
|
converterSet.add(TimeZoneConverter.INSTANCE);
|
||||||
|
converterSet.add(ZoneIdConverter.INSTANCE);
|
||||||
|
|
||||||
this.converterSet = converterSet;
|
this.converterSet = converterSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,8 +17,10 @@
|
|||||||
package org.dromara.hutool.core.convert.impl;
|
package org.dromara.hutool.core.convert.impl;
|
||||||
|
|
||||||
import org.dromara.hutool.core.convert.AbstractConverter;
|
import org.dromara.hutool.core.convert.AbstractConverter;
|
||||||
|
import org.dromara.hutool.core.convert.MatcherConverter;
|
||||||
import org.dromara.hutool.core.date.ZoneUtil;
|
import org.dromara.hutool.core.date.ZoneUtil;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
@ -27,9 +29,19 @@ import java.util.TimeZone;
|
|||||||
* @author Looly
|
* @author Looly
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class TimeZoneConverter extends AbstractConverter{
|
public class TimeZoneConverter extends AbstractConverter implements MatcherConverter {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单例
|
||||||
|
*/
|
||||||
|
public static final TimeZoneConverter INSTANCE = new TimeZoneConverter();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean match(final Type targetType, final Class<?> rawType, final Object value) {
|
||||||
|
return TimeZone.class.isAssignableFrom(rawType);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected TimeZone convertInternal(final Class<?> targetClass, final Object value) {
|
protected TimeZone convertInternal(final Class<?> targetClass, final Object value) {
|
||||||
if(value instanceof ZoneId){
|
if(value instanceof ZoneId){
|
||||||
@ -37,5 +49,4 @@ public class TimeZoneConverter extends AbstractConverter{
|
|||||||
}
|
}
|
||||||
return TimeZone.getTimeZone(convertToStr(value));
|
return TimeZone.getTimeZone(convertToStr(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,10 @@
|
|||||||
package org.dromara.hutool.core.convert.impl;
|
package org.dromara.hutool.core.convert.impl;
|
||||||
|
|
||||||
import org.dromara.hutool.core.convert.AbstractConverter;
|
import org.dromara.hutool.core.convert.AbstractConverter;
|
||||||
|
import org.dromara.hutool.core.convert.MatcherConverter;
|
||||||
import org.dromara.hutool.core.date.ZoneUtil;
|
import org.dromara.hutool.core.date.ZoneUtil;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
@ -27,9 +29,19 @@ import java.util.TimeZone;
|
|||||||
*
|
*
|
||||||
* @author Looly
|
* @author Looly
|
||||||
*/
|
*/
|
||||||
public class ZoneIdConverter extends AbstractConverter {
|
public class ZoneIdConverter extends AbstractConverter implements MatcherConverter {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单例
|
||||||
|
*/
|
||||||
|
public static final ZoneIdConverter INSTANCE = new ZoneIdConverter();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean match(final Type targetType, final Class<?> rawType, final Object value) {
|
||||||
|
return ZoneId.class.isAssignableFrom(rawType);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ZoneId convertInternal(final Class<?> targetClass, final Object value) {
|
protected ZoneId convertInternal(final Class<?> targetClass, final Object value) {
|
||||||
if (value instanceof TimeZone) {
|
if (value instanceof TimeZone) {
|
||||||
@ -37,5 +49,4 @@ public class ZoneIdConverter extends AbstractConverter {
|
|||||||
}
|
}
|
||||||
return ZoneId.of(convertToStr(value));
|
return ZoneId.of(convertToStr(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,7 @@ public class DateTime extends Date {
|
|||||||
/**
|
/**
|
||||||
* 时区
|
* 时区
|
||||||
*/
|
*/
|
||||||
private TimeZone timeZone;
|
private transient TimeZone timeZone;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 第一周最少天数
|
* 第一周最少天数
|
||||||
|
@ -24,6 +24,7 @@ import org.dromara.hutool.core.lang.Opt;
|
|||||||
import org.dromara.hutool.core.map.reference.WeakConcurrentMap;
|
import org.dromara.hutool.core.map.reference.WeakConcurrentMap;
|
||||||
import org.dromara.hutool.core.reflect.ClassDescUtil;
|
import org.dromara.hutool.core.reflect.ClassDescUtil;
|
||||||
import org.dromara.hutool.core.reflect.ModifierUtil;
|
import org.dromara.hutool.core.reflect.ModifierUtil;
|
||||||
|
import org.dromara.hutool.core.reflect.method.MethodInvoker;
|
||||||
import org.dromara.hutool.core.reflect.method.MethodUtil;
|
import org.dromara.hutool.core.reflect.method.MethodUtil;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@ -171,9 +172,9 @@ public class LambdaUtil {
|
|||||||
* @param <R> getter方法返回值类型
|
* @param <R> getter方法返回值类型
|
||||||
* @return Obj::getXxx
|
* @return Obj::getXxx
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public static <T, R> Function<T, R> buildGetter(final Class<T> clazz, final String fieldName) {
|
public static <T, R> Function<T, R> buildGetter(final Class<T> clazz, final String fieldName) {
|
||||||
return LambdaFactory.build(Function.class, BeanUtil.getBeanDesc(clazz).getGetter(fieldName));
|
final MethodInvoker getter = (MethodInvoker) BeanUtil.getBeanDesc(clazz).getGetter(fieldName);
|
||||||
|
return buildGetter(getter.getMethod());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -205,9 +206,9 @@ public class LambdaUtil {
|
|||||||
* @param <P> setter方法返回的值类型
|
* @param <P> setter方法返回的值类型
|
||||||
* @return Obj::setXxx
|
* @return Obj::setXxx
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public static <T, P> BiConsumer<T, P> buildSetter(final Class<T> clazz, final String fieldName) {
|
public static <T, P> BiConsumer<T, P> buildSetter(final Class<T> clazz, final String fieldName) {
|
||||||
return LambdaFactory.build(BiConsumer.class, BeanUtil.getBeanDesc(clazz).getSetter(fieldName));
|
final MethodInvoker setter = (MethodInvoker) BeanUtil.getBeanDesc(clazz).getSetter(fieldName);
|
||||||
|
return buildSetter(setter.getMethod());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -163,6 +163,19 @@ public class Opt<T> {
|
|||||||
return this.value;
|
return this.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回包裹里的元素,取不到则抛出异常
|
||||||
|
*
|
||||||
|
* @return 包裹里的元素
|
||||||
|
* @throws NoSuchElementException 如果元素为空,则抛出此异常
|
||||||
|
*/
|
||||||
|
public T getOrThrow() throws NoSuchElementException {
|
||||||
|
if (this.value == null) {
|
||||||
|
throw new NoSuchElementException("No value present");
|
||||||
|
}
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断包裹里元素的值是否不存在,不存在为 {@code true},否则为{@code false}
|
* 判断包裹里元素的值是否不存在,不存在为 {@code true},否则为{@code false}
|
||||||
*
|
*
|
||||||
|
@ -22,6 +22,7 @@ import org.dromara.hutool.core.exception.HutoolException;
|
|||||||
import org.dromara.hutool.core.lang.Assert;
|
import org.dromara.hutool.core.lang.Assert;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 字段调用器<br>
|
* 字段调用器<br>
|
||||||
@ -30,7 +31,7 @@ import java.lang.reflect.Field;
|
|||||||
* <pre>{@code
|
* <pre>{@code
|
||||||
* FieldInvoker.of(Field).invoke(obj);
|
* FieldInvoker.of(Field).invoke(obj);
|
||||||
* }</pre>
|
* }</pre>
|
||||||
*
|
* <p>
|
||||||
* 赋值字段值:
|
* 赋值字段值:
|
||||||
* <pre>{@code
|
* <pre>{@code
|
||||||
* FieldInvoker.of(Field).invoke(obj, value);
|
* FieldInvoker.of(Field).invoke(obj, value);
|
||||||
@ -60,7 +61,32 @@ public class FieldInvoker implements Invoker {
|
|||||||
* @param field 字段
|
* @param field 字段
|
||||||
*/
|
*/
|
||||||
public FieldInvoker(final Field field) {
|
public FieldInvoker(final Field field) {
|
||||||
this.field = Assert.notNull(field);;
|
this.field = Assert.notNull(field);
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取字段
|
||||||
|
*
|
||||||
|
* @return 字段
|
||||||
|
*/
|
||||||
|
public Field getField() {
|
||||||
|
return this.field;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return this.field.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType() {
|
||||||
|
return field.getGenericType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getTypeClass() {
|
||||||
|
return field.getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -77,10 +103,10 @@ public class FieldInvoker implements Invoker {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public <T> T invoke(final Object target, final Object... args) {
|
public <T> T invoke(final Object target, final Object... args) {
|
||||||
if(ArrayUtil.isEmpty(args)){
|
if (ArrayUtil.isEmpty(args)) {
|
||||||
// 默认取值
|
// 默认取值
|
||||||
return (T) invokeGet(target);
|
return (T) invokeGet(target);
|
||||||
} else if(args.length == 1){
|
} else if (args.length == 1) {
|
||||||
invokeSet(target, args[0]);
|
invokeSet(target, args[0]);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -130,19 +156,14 @@ public class FieldInvoker implements Invoker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getType() {
|
|
||||||
return field.getType();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 转换值类型
|
* 转换值类型
|
||||||
*
|
*
|
||||||
* @param value 值
|
* @param value 值
|
||||||
* @return 转换后的值
|
* @return 转换后的值
|
||||||
*/
|
*/
|
||||||
private Object convertValue(final Object value){
|
private Object convertValue(final Object value) {
|
||||||
if(null == converter){
|
if (null == converter) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package org.dromara.hutool.core.reflect;
|
package org.dromara.hutool.core.reflect;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoker接口定义了调用目标对象的方法的规范。<br>
|
* Invoker接口定义了调用目标对象的方法的规范。<br>
|
||||||
* 它允许动态地调用方法,增强了代码的灵活性和扩展性。<br>
|
* 它允许动态地调用方法,增强了代码的灵活性和扩展性。<br>
|
||||||
@ -36,10 +38,24 @@ public interface Invoker {
|
|||||||
<T> T invoke(Object target, Object... args);
|
<T> T invoke(Object target, Object... args);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取调用方法的返回类型或参数类型。
|
* 获取调用方法的名称。
|
||||||
|
*
|
||||||
|
* @return 调用方法的名称,作为字符串返回。
|
||||||
|
*/
|
||||||
|
String getName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取调用方法的返回类型或参数类型或字段类型。
|
||||||
*
|
*
|
||||||
* @return 调用方法的返回类型,作为Class对象返回。
|
* @return 调用方法的返回类型,作为Class对象返回。
|
||||||
*/
|
*/
|
||||||
Class<?> getType();
|
Type getType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取调用方法的返回类型或参数类型或字段类型。
|
||||||
|
*
|
||||||
|
* @return 调用方法的返回类型,作为Class对象返回。
|
||||||
|
*/
|
||||||
|
Class<?> getTypeClass();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,12 +20,7 @@ import org.dromara.hutool.core.array.ArrayUtil;
|
|||||||
import org.dromara.hutool.core.collection.ListUtil;
|
import org.dromara.hutool.core.collection.ListUtil;
|
||||||
import org.dromara.hutool.core.util.ObjUtil;
|
import org.dromara.hutool.core.util.ObjUtil;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.*;
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.lang.reflect.TypeVariable;
|
|
||||||
import java.lang.reflect.WildcardType;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -66,6 +61,8 @@ public class TypeUtil {
|
|||||||
if (upperBounds.length == 1) {
|
if (upperBounds.length == 1) {
|
||||||
return getClass(upperBounds[0]);
|
return getClass(upperBounds[0]);
|
||||||
}
|
}
|
||||||
|
} else if(type instanceof GenericArrayType){
|
||||||
|
return Array.newInstance(getClass(((GenericArrayType)type).getGenericComponentType()), 0).getClass();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -18,12 +18,11 @@ package org.dromara.hutool.core.reflect.method;
|
|||||||
|
|
||||||
import org.dromara.hutool.core.exception.HutoolException;
|
import org.dromara.hutool.core.exception.HutoolException;
|
||||||
import org.dromara.hutool.core.lang.Assert;
|
import org.dromara.hutool.core.lang.Assert;
|
||||||
import org.dromara.hutool.core.reflect.ClassUtil;
|
import org.dromara.hutool.core.reflect.*;
|
||||||
import org.dromara.hutool.core.reflect.Invoker;
|
|
||||||
import org.dromara.hutool.core.reflect.ModifierUtil;
|
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 方法调用器,通过反射调用方法。
|
* 方法调用器,通过反射调用方法。
|
||||||
@ -43,8 +42,10 @@ public class MethodInvoker implements Invoker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final Method method;
|
private final Method method;
|
||||||
private final Class<?>[] paramTypes;
|
private final Type[] paramTypes;
|
||||||
private final Class<?> type;
|
private final Class<?>[] paramTypeClasses;
|
||||||
|
private final Type type;
|
||||||
|
private final Class<?> typeClass;
|
||||||
private boolean checkArgs;
|
private boolean checkArgs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -53,17 +54,53 @@ public class MethodInvoker implements Invoker {
|
|||||||
* @param method 方法
|
* @param method 方法
|
||||||
*/
|
*/
|
||||||
public MethodInvoker(final Method method) {
|
public MethodInvoker(final Method method) {
|
||||||
this.method = method;
|
this.method = ReflectUtil.setAccessible(Assert.notNull(method));
|
||||||
|
|
||||||
this.paramTypes = method.getParameterTypes();
|
this.paramTypes = TypeUtil.getParamTypes(method);
|
||||||
|
this.paramTypeClasses = method.getParameterTypes();
|
||||||
if (paramTypes.length == 1) {
|
if (paramTypes.length == 1) {
|
||||||
// setter方法读取参数类型
|
// setter方法读取参数类型
|
||||||
type = paramTypes[0];
|
type = paramTypes[0];
|
||||||
|
typeClass = paramTypeClasses[0];
|
||||||
} else {
|
} else {
|
||||||
type = method.getReturnType();
|
type = method.getReturnType();
|
||||||
|
typeClass = method.getReturnType();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取方法
|
||||||
|
*
|
||||||
|
* @return 方法
|
||||||
|
*/
|
||||||
|
public Method getMethod() {
|
||||||
|
return this.method;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取方法参数类型
|
||||||
|
*
|
||||||
|
* @return 方法参数类型
|
||||||
|
*/
|
||||||
|
public Type[] getParamTypes() {
|
||||||
|
return this.paramTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return this.method.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType() {
|
||||||
|
return this.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getTypeClass() {
|
||||||
|
return this.typeClass;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置是否检查参数<br>
|
* 设置是否检查参数<br>
|
||||||
* <pre>
|
* <pre>
|
||||||
@ -81,19 +118,21 @@ public class MethodInvoker implements Invoker {
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public <T> T invoke(Object target, final Object... args) throws HutoolException{
|
public <T> T invoke(Object target, final Object... args) throws HutoolException {
|
||||||
if(this.checkArgs){
|
if (this.checkArgs) {
|
||||||
checkArgs(args);
|
checkArgs(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Method method = this.method;
|
final Method method = this.method;
|
||||||
// static方法调用则target为null
|
// static方法调用则target为null
|
||||||
if(ModifierUtil.isStatic(method)){
|
if (ModifierUtil.isStatic(method)) {
|
||||||
target = null;
|
target = null;
|
||||||
}
|
}
|
||||||
// 根据方法定义的参数类型,将用户传入的参数规整和转换
|
// 根据方法定义的参数类型,将用户传入的参数规整和转换
|
||||||
final Object[] actualArgs = MethodUtil.actualArgs(method, args);
|
final Object[] actualArgs = MethodUtil.actualArgs(method, args);
|
||||||
try {
|
try {
|
||||||
|
// issue#3671 JDK15+ 修改了lambda的策略,动态生成后在metaspace不会释放,导致资源占用高
|
||||||
|
//return (T) LambdaUtil.buildGetter(method).apply(target);
|
||||||
return MethodHandleUtil.invokeExact(target, method, actualArgs);
|
return MethodHandleUtil.invokeExact(target, method, actualArgs);
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
// 传统反射方式执行方法
|
// 传统反射方式执行方法
|
||||||
@ -117,11 +156,6 @@ public class MethodInvoker implements Invoker {
|
|||||||
return invoke(null, args);
|
return invoke(null, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getType() {
|
|
||||||
return this.type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查传入参数的有效性。
|
* 检查传入参数的有效性。
|
||||||
*
|
*
|
||||||
@ -129,12 +163,12 @@ public class MethodInvoker implements Invoker {
|
|||||||
* @throws IllegalArgumentException 如果参数数组为空或长度为0,则抛出此异常。
|
* @throws IllegalArgumentException 如果参数数组为空或长度为0,则抛出此异常。
|
||||||
*/
|
*/
|
||||||
private void checkArgs(final Object[] args) {
|
private void checkArgs(final Object[] args) {
|
||||||
final Class<?>[] paramTypes = this.paramTypes;
|
final Class<?>[] paramTypeClasses = this.paramTypeClasses;
|
||||||
if (null != args) {
|
if (null != args) {
|
||||||
Assert.isTrue(args.length == paramTypes.length, "Params length [{}] is not fit for param length [{}] of method !", args.length, paramTypes.length);
|
Assert.isTrue(args.length == paramTypeClasses.length, "Params length [{}] is not fit for param length [{}] of method !", args.length, paramTypeClasses.length);
|
||||||
Class<?> type;
|
Class<?> type;
|
||||||
for (int i = 0; i < args.length; i++) {
|
for (int i = 0; i < args.length; i++) {
|
||||||
type = paramTypes[i];
|
type = paramTypeClasses[i];
|
||||||
if (type.isPrimitive() && null == args[i]) {
|
if (type.isPrimitive() && null == args[i]) {
|
||||||
// 参数是原始类型,而传入参数为null时赋予默认值
|
// 参数是原始类型,而传入参数为null时赋予默认值
|
||||||
args[i] = ClassUtil.getDefaultValue(type);
|
args[i] = ClassUtil.getDefaultValue(type);
|
||||||
|
@ -20,6 +20,7 @@ import org.dromara.hutool.core.array.ArrayUtil;
|
|||||||
import org.dromara.hutool.core.collection.set.SetUtil;
|
import org.dromara.hutool.core.collection.set.SetUtil;
|
||||||
import org.dromara.hutool.core.text.StrUtil;
|
import org.dromara.hutool.core.text.StrUtil;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -532,11 +533,11 @@ public class BooleanUtil {
|
|||||||
/**
|
/**
|
||||||
* 给定类是否为Boolean或者boolean
|
* 给定类是否为Boolean或者boolean
|
||||||
*
|
*
|
||||||
* @param clazz 类
|
* @param type 类
|
||||||
* @return 是否为Boolean或者boolean
|
* @return 是否为Boolean或者boolean
|
||||||
* @since 4.5.2
|
* @since 4.5.2
|
||||||
*/
|
*/
|
||||||
public static boolean isBoolean(final Class<?> clazz) {
|
public static boolean isBoolean(final Type type) {
|
||||||
return (clazz == Boolean.class || clazz == boolean.class);
|
return (type == Boolean.class || type == boolean.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,9 +17,12 @@
|
|||||||
package org.dromara.hutool.core.bean;
|
package org.dromara.hutool.core.bean;
|
||||||
|
|
||||||
import org.dromara.hutool.core.bean.path.AbstractBeanDesc;
|
import org.dromara.hutool.core.bean.path.AbstractBeanDesc;
|
||||||
|
import org.dromara.hutool.core.reflect.method.MethodInvoker;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link StrictBeanDesc} 单元测试类
|
* {@link StrictBeanDesc} 单元测试类
|
||||||
*
|
*
|
||||||
@ -38,8 +41,10 @@ public class BeanDescTest {
|
|||||||
Assertions.assertEquals("age", desc.getProp("age").getFieldName());
|
Assertions.assertEquals("age", desc.getProp("age").getFieldName());
|
||||||
Assertions.assertEquals("getAge", desc.getGetter("age").getName());
|
Assertions.assertEquals("getAge", desc.getGetter("age").getName());
|
||||||
Assertions.assertEquals("setAge", desc.getSetter("age").getName());
|
Assertions.assertEquals("setAge", desc.getSetter("age").getName());
|
||||||
Assertions.assertEquals(1, desc.getSetter("age").getParameterTypes().length);
|
|
||||||
Assertions.assertSame(int.class, desc.getSetter("age").getParameterTypes()[0]);
|
final MethodInvoker setter = (MethodInvoker) desc.getSetter("age");
|
||||||
|
Assertions.assertEquals(1, setter.getMethod().getParameterTypes().length);
|
||||||
|
Assertions.assertSame(int.class, setter.getMethod().getParameterTypes()[0]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,8 +56,11 @@ public class BeanDescTest {
|
|||||||
Assertions.assertEquals("name", prop.getFieldName());
|
Assertions.assertEquals("name", prop.getFieldName());
|
||||||
Assertions.assertEquals("getName", prop.getGetter().getName());
|
Assertions.assertEquals("getName", prop.getGetter().getName());
|
||||||
Assertions.assertEquals("setName", prop.getSetter().getName());
|
Assertions.assertEquals("setName", prop.getSetter().getName());
|
||||||
Assertions.assertEquals(1, prop.getSetter().getParameterTypes().length);
|
|
||||||
Assertions.assertSame(String.class, prop.getSetter().getParameterTypes()[0]);
|
final MethodInvoker setter = (MethodInvoker) desc.getSetter("name");
|
||||||
|
final Method setterMethod = setter.getMethod();
|
||||||
|
Assertions.assertEquals(1, setterMethod.getParameterTypes().length);
|
||||||
|
Assertions.assertSame(String.class, setterMethod.getParameterTypes()[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -19,12 +19,11 @@ package org.dromara.hutool.db.handler.row;
|
|||||||
import org.dromara.hutool.core.bean.BeanUtil;
|
import org.dromara.hutool.core.bean.BeanUtil;
|
||||||
import org.dromara.hutool.core.bean.PropDesc;
|
import org.dromara.hutool.core.bean.PropDesc;
|
||||||
import org.dromara.hutool.core.reflect.ConstructorUtil;
|
import org.dromara.hutool.core.reflect.ConstructorUtil;
|
||||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
import org.dromara.hutool.core.reflect.Invoker;
|
||||||
import org.dromara.hutool.core.reflect.method.MethodUtil;
|
import org.dromara.hutool.core.reflect.method.MethodInvoker;
|
||||||
import org.dromara.hutool.core.text.StrUtil;
|
import org.dromara.hutool.core.text.StrUtil;
|
||||||
import org.dromara.hutool.db.handler.ResultSetUtil;
|
import org.dromara.hutool.db.handler.ResultSetUtil;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.ResultSetMetaData;
|
import java.sql.ResultSetMetaData;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
@ -63,7 +62,7 @@ public class BeanRowHandler<T> extends AbsRowHandler<T> {
|
|||||||
final Map<String, PropDesc> propMap = BeanUtil.getBeanDesc(beanType).getPropMap(this.caseInsensitive);
|
final Map<String, PropDesc> propMap = BeanUtil.getBeanDesc(beanType).getPropMap(this.caseInsensitive);
|
||||||
String columnLabel;
|
String columnLabel;
|
||||||
PropDesc pd;
|
PropDesc pd;
|
||||||
Method setter;
|
Invoker setter;
|
||||||
Object value;
|
Object value;
|
||||||
for (int i = 1; i <= columnCount; i++) {
|
for (int i = 1; i <= columnCount; i++) {
|
||||||
columnLabel = meta.getColumnLabel(i);
|
columnLabel = meta.getColumnLabel(i);
|
||||||
@ -74,8 +73,12 @@ public class BeanRowHandler<T> extends AbsRowHandler<T> {
|
|||||||
}
|
}
|
||||||
setter = (null == pd) ? null : pd.getSetter();
|
setter = (null == pd) ? null : pd.getSetter();
|
||||||
if (null != setter) {
|
if (null != setter) {
|
||||||
value = ResultSetUtil.getColumnValue(rs, i, meta.getColumnType(i), TypeUtil.getFirstParamType(setter));
|
value = ResultSetUtil.getColumnValue(rs, i, meta.getColumnType(i), setter.getType());
|
||||||
MethodUtil.invokeWithCheck(bean, setter, value);
|
if(setter instanceof MethodInvoker){
|
||||||
|
MethodInvoker.of(((MethodInvoker) setter).getMethod()).setCheckArgs(true).invoke(bean, value);
|
||||||
|
}else {
|
||||||
|
setter.invoke(bean, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return bean;
|
return bean;
|
||||||
|
@ -20,6 +20,7 @@ import org.dromara.hutool.core.bean.path.BeanPath;
|
|||||||
import org.dromara.hutool.core.convert.ConvertException;
|
import org.dromara.hutool.core.convert.ConvertException;
|
||||||
import org.dromara.hutool.core.convert.Converter;
|
import org.dromara.hutool.core.convert.Converter;
|
||||||
import org.dromara.hutool.core.lang.mutable.MutableEntry;
|
import org.dromara.hutool.core.lang.mutable.MutableEntry;
|
||||||
|
import org.dromara.hutool.core.util.ObjUtil;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
@ -43,7 +44,7 @@ public interface JSON extends Converter, Cloneable, Serializable {
|
|||||||
JSONConfig config();
|
JSONConfig config();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JSON大小,对于JSONObject,是键值对的多少,JSONArray则是元素的个数
|
* JSON大小,对于JSONObject,是键值对的多少,JSONArray则是元素的个数,JSON原始数据为1
|
||||||
*
|
*
|
||||||
* @return 大小
|
* @return 大小
|
||||||
*/
|
*/
|
||||||
@ -192,6 +193,6 @@ public interface JSON extends Converter, Cloneable, Serializable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
default Object convert(final Type targetType, final Object value) throws ConvertException {
|
default Object convert(final Type targetType, final Object value) throws ConvertException {
|
||||||
return config().getConverter().convert(targetType, value);
|
return ObjUtil.defaultIfNull(config(), JSONConfig::of).getConverter().convert(targetType, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Hutool Team and hutool.cn
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.dromara.hutool.json;
|
||||||
|
|
||||||
|
import org.dromara.hutool.core.lang.Assert;
|
||||||
|
import org.dromara.hutool.core.lang.mutable.MutableEntry;
|
||||||
|
import org.dromara.hutool.json.writer.GlobalValueWriters;
|
||||||
|
import org.dromara.hutool.json.writer.JSONValueWriter;
|
||||||
|
import org.dromara.hutool.json.writer.JSONWriter;
|
||||||
|
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JSON原始类型数据封装,根据RFC8259规范,JSONPrimitive只包含以下类型:
|
||||||
|
* <ul>
|
||||||
|
* <li>number</li>
|
||||||
|
* <li>string</li>
|
||||||
|
* <li>null</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @author Looly
|
||||||
|
* @since 6.0.0
|
||||||
|
*/
|
||||||
|
public class JSONPrimitive implements JSON {
|
||||||
|
private static final long serialVersionUID = -2026215279191790345L;
|
||||||
|
|
||||||
|
private Object value;
|
||||||
|
/**
|
||||||
|
* 配置项
|
||||||
|
*/
|
||||||
|
private JSONConfig config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param value 值
|
||||||
|
*/
|
||||||
|
public JSONPrimitive(final Object value) {
|
||||||
|
this(value, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param value 值
|
||||||
|
* @param config 配置项
|
||||||
|
*/
|
||||||
|
public JSONPrimitive(final Object value, final JSONConfig config) {
|
||||||
|
this.value = Assert.notNull(value);
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取值
|
||||||
|
*
|
||||||
|
* @return 值
|
||||||
|
*/
|
||||||
|
public Object getValue() {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置值
|
||||||
|
*
|
||||||
|
* @param value 值
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public JSONPrimitive setValue(final Object value) {
|
||||||
|
this.value = value;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONConfig config() {
|
||||||
|
return this.config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置配置项
|
||||||
|
*
|
||||||
|
* @param config 配置项
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
JSONPrimitive setConfig(final JSONConfig config) {
|
||||||
|
this.config = config;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Writer write(final Writer writer, final int indentFactor, final int indent, final Predicate<MutableEntry<Object, Object>> predicate) throws JSONException {
|
||||||
|
final Object value = this.value;
|
||||||
|
final JSONWriter jsonWriter = JSONWriter.of(writer, indentFactor, indent, config);
|
||||||
|
|
||||||
|
// 自定义规则
|
||||||
|
final JSONValueWriter valueWriter = GlobalValueWriters.get(value);
|
||||||
|
if (null != valueWriter) {
|
||||||
|
valueWriter.write(jsonWriter, value);
|
||||||
|
return writer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认包装字符串
|
||||||
|
jsonWriter.writeQuoteStrValue(value.toString());
|
||||||
|
return writer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
final StringWriter sw = new StringWriter();
|
||||||
|
return this.write(sw, 0, 0, null).toString();
|
||||||
|
}
|
||||||
|
}
|
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package org.dromara.hutool.json;
|
package org.dromara.hutool.json;
|
||||||
|
|
||||||
import org.dromara.hutool.core.convert.ConvertUtil;
|
|
||||||
import org.dromara.hutool.core.io.IORuntimeException;
|
import org.dromara.hutool.core.io.IORuntimeException;
|
||||||
import org.dromara.hutool.core.io.file.FileUtil;
|
import org.dromara.hutool.core.io.file.FileUtil;
|
||||||
import org.dromara.hutool.core.lang.Assert;
|
import org.dromara.hutool.core.lang.Assert;
|
||||||
@ -161,7 +160,7 @@ public class JSONUtil {
|
|||||||
* @param obj 对象
|
* @param obj 对象
|
||||||
* @return JSON
|
* @return JSON
|
||||||
*/
|
*/
|
||||||
public static Object parse(final Object obj) {
|
public static JSON parse(final Object obj) {
|
||||||
return parse(obj, null);
|
return parse(obj, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,7 +177,7 @@ public class JSONUtil {
|
|||||||
* @param config JSON配置,{@code null}使用默认配置
|
* @param config JSON配置,{@code null}使用默认配置
|
||||||
* @return JSON(JSONObject or JSONArray)
|
* @return JSON(JSONObject or JSONArray)
|
||||||
*/
|
*/
|
||||||
public static Object parse(final Object obj, final JSONConfig config) {
|
public static JSON parse(final Object obj, final JSONConfig config) {
|
||||||
if (null == config) {
|
if (null == config) {
|
||||||
return JSONConverter.INSTANCE.toJSON(obj);
|
return JSONConverter.INSTANCE.toJSON(obj);
|
||||||
}
|
}
|
||||||
@ -378,26 +377,21 @@ public class JSONUtil {
|
|||||||
* 转为实体类对象
|
* 转为实体类对象
|
||||||
*
|
*
|
||||||
* @param <T> Bean类型
|
* @param <T> Bean类型
|
||||||
* @param json JSONObject
|
* @param obj JSONObject
|
||||||
* @param config JSON配置
|
* @param config JSON配置
|
||||||
* @param type 实体类对象类型
|
* @param type 实体类对象类型
|
||||||
* @return 实体类对象
|
* @return 实体类对象
|
||||||
* @since 4.3.2
|
* @since 4.3.2
|
||||||
*/
|
*/
|
||||||
public static <T> T toBean(Object json, final JSONConfig config, Type type) {
|
public static <T> T toBean(final Object obj, final JSONConfig config, Type type) {
|
||||||
if (null == json) {
|
if (null == obj) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
json = parse(json, config);
|
final JSON json = parse(obj, config);
|
||||||
if (json instanceof JSON) {
|
|
||||||
if (type instanceof TypeReference) {
|
if (type instanceof TypeReference) {
|
||||||
type = ((TypeReference<?>) type).getType();
|
type = ((TypeReference<?>) type).getType();
|
||||||
}
|
}
|
||||||
return ((JSON) json).toBean(type);
|
return json.toBean(type);
|
||||||
}
|
|
||||||
|
|
||||||
//issue#I7CW27,其他类型使用默认转换
|
|
||||||
return ConvertUtil.convert(type, json);
|
|
||||||
}
|
}
|
||||||
// -------------------------------------------------------------------- toBean end
|
// -------------------------------------------------------------------- toBean end
|
||||||
|
|
||||||
|
@ -29,7 +29,6 @@ import org.dromara.hutool.core.reflect.TypeReference;
|
|||||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||||
import org.dromara.hutool.core.reflect.kotlin.KClassUtil;
|
import org.dromara.hutool.core.reflect.kotlin.KClassUtil;
|
||||||
import org.dromara.hutool.core.text.StrUtil;
|
import org.dromara.hutool.core.text.StrUtil;
|
||||||
import org.dromara.hutool.core.util.ObjUtil;
|
|
||||||
import org.dromara.hutool.json.*;
|
import org.dromara.hutool.json.*;
|
||||||
import org.dromara.hutool.json.serialize.JSONDeserializer;
|
import org.dromara.hutool.json.serialize.JSONDeserializer;
|
||||||
import org.dromara.hutool.json.serialize.JSONStringer;
|
import org.dromara.hutool.json.serialize.JSONStringer;
|
||||||
@ -63,6 +62,7 @@ public class JSONConverter implements Converter, Serializable {
|
|||||||
final RegisterConverter converter = RegisterConverter.getInstance();
|
final RegisterConverter converter = RegisterConverter.getInstance();
|
||||||
converter.register(JSONObject.class, INSTANCE);
|
converter.register(JSONObject.class, INSTANCE);
|
||||||
converter.register(JSONArray.class, INSTANCE);
|
converter.register(JSONArray.class, INSTANCE);
|
||||||
|
converter.register(JSONPrimitive.class, INSTANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -137,7 +137,7 @@ public class JSONConverter implements Converter, Serializable {
|
|||||||
* @return 转换后的对象
|
* @return 转换后的对象
|
||||||
* @throws JSONException 转换异常
|
* @throws JSONException 转换异常
|
||||||
*/
|
*/
|
||||||
public Object toJSON(Object obj) throws JSONException {
|
public JSON toJSON(Object obj) throws JSONException {
|
||||||
if (null == obj) {
|
if (null == obj) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -148,10 +148,17 @@ public class JSONConverter implements Converter, Serializable {
|
|||||||
obj = ((Opt<?>) obj).getOrNull();
|
obj = ((Opt<?>) obj).getOrNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(obj instanceof JSON){
|
||||||
|
return (JSON) obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj instanceof Number || obj instanceof Boolean) {
|
||||||
|
// RFC8259规范的原始类型数据
|
||||||
|
return new JSONPrimitive(obj, config);
|
||||||
|
}
|
||||||
|
|
||||||
final JSON json;
|
final JSON json;
|
||||||
if (obj instanceof JSON || obj instanceof Number || obj instanceof Boolean) {
|
if (obj instanceof CharSequence) {
|
||||||
return obj;
|
|
||||||
} else if (obj instanceof CharSequence) {
|
|
||||||
return toJSON((CharSequence) obj);
|
return toJSON((CharSequence) obj);
|
||||||
} else if (obj instanceof MapWrapper) {
|
} else if (obj instanceof MapWrapper) {
|
||||||
// MapWrapper实现了Iterable会被当作JSONArray,此处做修正
|
// MapWrapper实现了Iterable会被当作JSONArray,此处做修正
|
||||||
@ -173,7 +180,7 @@ public class JSONConverter implements Converter, Serializable {
|
|||||||
* @return 转换后的对象
|
* @return 转换后的对象
|
||||||
* @throws JSONException 转换异常
|
* @throws JSONException 转换异常
|
||||||
*/
|
*/
|
||||||
public Object toJSON(final CharSequence str) throws JSONException {
|
public JSON toJSON(final CharSequence str) throws JSONException {
|
||||||
if (null == str) {
|
if (null == str) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -184,7 +191,7 @@ public class JSONConverter implements Converter, Serializable {
|
|||||||
// 未被包装的空串理解为null
|
// 未被包装的空串理解为null
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final char firstC = jsonStr.charAt(0);
|
|
||||||
// RFC8259,JSON字符串值、number, boolean, or null
|
// RFC8259,JSON字符串值、number, boolean, or null
|
||||||
final JSONParser jsonParser = JSONParser.of(new JSONTokener(jsonStr), config);
|
final JSONParser jsonParser = JSONParser.of(new JSONTokener(jsonStr), config);
|
||||||
final Object value = jsonParser.nextValue();
|
final Object value = jsonParser.nextValue();
|
||||||
@ -192,17 +199,10 @@ public class JSONConverter implements Converter, Serializable {
|
|||||||
// 对于用户提供的未转义字符串导致解析未结束,报错
|
// 对于用户提供的未转义字符串导致解析未结束,报错
|
||||||
throw new JSONException("JSON format error: {}", jsonStr);
|
throw new JSONException("JSON format error: {}", jsonStr);
|
||||||
}
|
}
|
||||||
switch (firstC) {
|
if(null == value || value instanceof JSON){
|
||||||
case '"':
|
return (JSON) value;
|
||||||
case '\'':
|
|
||||||
return InternalJSONUtil.quote((CharSequence) value);
|
|
||||||
default:
|
|
||||||
if (ObjUtil.equals(jsonStr, value)) {
|
|
||||||
// 对于直接的字符串,如abc,按照字符串处理
|
|
||||||
return InternalJSONUtil.quote((CharSequence) value);
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
return new JSONPrimitive(value, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------- Private method start
|
// ----------------------------------------------------------- Private method start
|
||||||
@ -220,16 +220,16 @@ public class JSONConverter implements Converter, Serializable {
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private <T> T toBean(final Type targetType, final JSON json) {
|
private <T> T toBean(final Type targetType, final JSON json) {
|
||||||
|
|
||||||
// 自定义对象反序列化
|
// 自定义对象反序列化
|
||||||
final JSONDeserializer<Object> deserializer = InternalJSONUtil.getDeserializer(targetType);
|
final JSONDeserializer<Object> deserializer = InternalJSONUtil.getDeserializer(targetType);
|
||||||
|
|
||||||
if (null != deserializer) {
|
if (null != deserializer) {
|
||||||
return (T) deserializer.deserialize(json);
|
return (T) deserializer.deserialize(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 当目标类型不确定时,返回原JSON
|
||||||
final Class<T> rawType = (Class<T>) TypeUtil.getClass(targetType);
|
final Class<T> rawType = (Class<T>) TypeUtil.getClass(targetType);
|
||||||
if (null == rawType) {
|
if (null == rawType) {
|
||||||
// 当目标类型不确定时,返回原JSON
|
|
||||||
return (T) json;
|
return (T) json;
|
||||||
//throw new JSONException("Can not get class from type: {}", targetType);
|
//throw new JSONException("Can not get class from type: {}", targetType);
|
||||||
}
|
}
|
||||||
@ -239,21 +239,29 @@ public class JSONConverter implements Converter, Serializable {
|
|||||||
return KClassUtil.newInstance(rawType, new JSONGetterValueProvider<>((JSONGetter<String>) json));
|
return KClassUtil.newInstance(rawType, new JSONGetterValueProvider<>((JSONGetter<String>) json));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final Object value;
|
||||||
|
// JSON原始类型
|
||||||
|
if(json instanceof JSONPrimitive){
|
||||||
|
value = ((JSONPrimitive) json).getValue();
|
||||||
|
} else {
|
||||||
|
value = json;
|
||||||
|
}
|
||||||
|
|
||||||
// 标准转换器
|
// 标准转换器
|
||||||
final Converter converter = RegisterConverter.getInstance().getConverter(targetType, json, true);
|
final Converter converter = RegisterConverter.getInstance().getConverter(targetType, value, true);
|
||||||
if (null != converter) {
|
if (null != converter) {
|
||||||
return (T) converter.convert(targetType, json);
|
return (T) converter.convert(targetType, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 特殊类型转换,包括Collection、Map、强转、Array等
|
// 特殊类型转换,包括Collection、Map、强转、Array等
|
||||||
final T result = (T) SpecialConverter.getInstance().convert(targetType, rawType, json);
|
final T result = (T) SpecialConverter.getInstance().convert(targetType, rawType, value);
|
||||||
if (null != result) {
|
if (null != result) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 尝试转Bean
|
// 尝试转Bean
|
||||||
if (BeanUtil.isWritableBean(rawType)) {
|
if (BeanUtil.isWritableBean(rawType)) {
|
||||||
return BeanCopier.of(json,
|
return BeanCopier.of(value,
|
||||||
ConstructorUtil.newInstanceIfPossible(rawType), targetType,
|
ConstructorUtil.newInstanceIfPossible(rawType), targetType,
|
||||||
InternalJSONUtil.toCopyOptions(json.config())).copy();
|
InternalJSONUtil.toCopyOptions(json.config())).copy();
|
||||||
}
|
}
|
||||||
|
@ -38,14 +38,14 @@ public class HutoolJSONEngine extends AbstractJSONEngine {
|
|||||||
@Override
|
@Override
|
||||||
public void serialize(final Object bean, final Writer writer) {
|
public void serialize(final Object bean, final Writer writer) {
|
||||||
initEngine();
|
initEngine();
|
||||||
final JSON json = (JSON) JSONUtil.parse(bean, this.hutoolSJONConfig);
|
final JSON json = JSONUtil.parse(bean, this.hutoolSJONConfig);
|
||||||
json.write(writer, ObjUtil.defaultIfNull(this.config, JSONEngineConfig::isPrettyPrint, false) ? 2 : 0, 0, null);
|
json.write(writer, ObjUtil.defaultIfNull(this.config, JSONEngineConfig::isPrettyPrint, false) ? 2 : 0, 0, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T deserialize(final Reader reader, final Object type) {
|
public <T> T deserialize(final Reader reader, final Object type) {
|
||||||
initEngine();
|
initEngine();
|
||||||
final JSON json = (JSON) JSONUtil.parse(reader, this.hutoolSJONConfig);
|
final JSON json = JSONUtil.parse(reader, this.hutoolSJONConfig);
|
||||||
return json.toBean((Type) type);
|
return json.toBean((Type) type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ package org.dromara.hutool.json.engine.gson;
|
|||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import org.dromara.hutool.core.lang.Assert;
|
import org.dromara.hutool.core.lang.Assert;
|
||||||
|
import org.dromara.hutool.core.lang.wrapper.Wrapper;
|
||||||
import org.dromara.hutool.core.util.ObjUtil;
|
import org.dromara.hutool.core.util.ObjUtil;
|
||||||
import org.dromara.hutool.json.JSONException;
|
import org.dromara.hutool.json.JSONException;
|
||||||
import org.dromara.hutool.json.engine.AbstractJSONEngine;
|
import org.dromara.hutool.json.engine.AbstractJSONEngine;
|
||||||
@ -31,6 +32,7 @@ import java.time.LocalDate;
|
|||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.LocalTime;
|
import java.time.LocalTime;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gson引擎实现
|
* Gson引擎实现
|
||||||
@ -38,7 +40,7 @@ import java.util.Date;
|
|||||||
* @author Looly
|
* @author Looly
|
||||||
* @since 6.0.0
|
* @since 6.0.0
|
||||||
*/
|
*/
|
||||||
public class GsonEngine extends AbstractJSONEngine {
|
public class GsonEngine extends AbstractJSONEngine implements Wrapper<Gson> {
|
||||||
|
|
||||||
private Gson gson;
|
private Gson gson;
|
||||||
|
|
||||||
@ -51,6 +53,12 @@ public class GsonEngine extends AbstractJSONEngine {
|
|||||||
Assert.notNull(Gson.class);
|
Assert.notNull(Gson.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Gson getRaw() {
|
||||||
|
initEngine();
|
||||||
|
return this.gson;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void serialize(final Object bean, final Writer writer) {
|
public void serialize(final Object bean, final Writer writer) {
|
||||||
initEngine();
|
initEngine();
|
||||||
@ -106,7 +114,11 @@ public class GsonEngine extends AbstractJSONEngine {
|
|||||||
* @param dateFormat 日期格式
|
* @param dateFormat 日期格式
|
||||||
*/
|
*/
|
||||||
private void registerDate(final GsonBuilder builder, final String dateFormat){
|
private void registerDate(final GsonBuilder builder, final String dateFormat){
|
||||||
builder.registerTypeAdapter(Date.class, new DateSerDesc(dateFormat));
|
// java date
|
||||||
|
builder.registerTypeHierarchyAdapter(Date.class, new DateSerDesc(dateFormat));
|
||||||
|
builder.registerTypeHierarchyAdapter(TimeZone.class, TimeZoneSerDesc.INSTANCE);
|
||||||
|
|
||||||
|
// java.time
|
||||||
builder.registerTypeAdapter(LocalDateTime.class, new TemporalSerDesc(LocalDateTime.class, dateFormat));
|
builder.registerTypeAdapter(LocalDateTime.class, new TemporalSerDesc(LocalDateTime.class, dateFormat));
|
||||||
builder.registerTypeAdapter(LocalDate.class, new TemporalSerDesc(LocalDate.class, dateFormat));
|
builder.registerTypeAdapter(LocalDate.class, new TemporalSerDesc(LocalDate.class, dateFormat));
|
||||||
builder.registerTypeAdapter(LocalTime.class, new TemporalSerDesc(LocalTime.class, dateFormat));
|
builder.registerTypeAdapter(LocalTime.class, new TemporalSerDesc(LocalTime.class, dateFormat));
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Hutool Team and hutool.cn
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.dromara.hutool.json.engine.gson;
|
||||||
|
|
||||||
|
import com.google.gson.*;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 时区序列化描述
|
||||||
|
*
|
||||||
|
* @author Looly
|
||||||
|
* @since 6.0.0
|
||||||
|
*/
|
||||||
|
public class TimeZoneSerDesc implements GsonSerDesc<TimeZone>{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认时区格式化描述
|
||||||
|
*/
|
||||||
|
public static final TimeZoneSerDesc INSTANCE = new TimeZoneSerDesc();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsonElement serialize(final TimeZone src, final Type typeOfSrc, final JsonSerializationContext context) {
|
||||||
|
return new JsonPrimitive(src.getID());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TimeZone deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context) throws JsonParseException {
|
||||||
|
return TimeZone.getTimeZone(json.getAsString());
|
||||||
|
}
|
||||||
|
}
|
@ -26,6 +26,7 @@ import com.fasterxml.jackson.databind.SerializationFeature;
|
|||||||
import org.dromara.hutool.core.date.DateUtil;
|
import org.dromara.hutool.core.date.DateUtil;
|
||||||
import org.dromara.hutool.core.io.IORuntimeException;
|
import org.dromara.hutool.core.io.IORuntimeException;
|
||||||
import org.dromara.hutool.core.lang.Assert;
|
import org.dromara.hutool.core.lang.Assert;
|
||||||
|
import org.dromara.hutool.core.lang.wrapper.Wrapper;
|
||||||
import org.dromara.hutool.core.reflect.ConstructorUtil;
|
import org.dromara.hutool.core.reflect.ConstructorUtil;
|
||||||
import org.dromara.hutool.core.text.StrUtil;
|
import org.dromara.hutool.core.text.StrUtil;
|
||||||
import org.dromara.hutool.core.util.ObjUtil;
|
import org.dromara.hutool.core.util.ObjUtil;
|
||||||
@ -42,7 +43,7 @@ import java.io.Writer;
|
|||||||
*
|
*
|
||||||
* @author Looly
|
* @author Looly
|
||||||
*/
|
*/
|
||||||
public class JacksonEngine extends AbstractJSONEngine {
|
public class JacksonEngine extends AbstractJSONEngine implements Wrapper<ObjectMapper> {
|
||||||
|
|
||||||
private ObjectMapper mapper;
|
private ObjectMapper mapper;
|
||||||
|
|
||||||
@ -60,7 +61,8 @@ public class JacksonEngine extends AbstractJSONEngine {
|
|||||||
*
|
*
|
||||||
* @return {@link ObjectMapper}对象
|
* @return {@link ObjectMapper}对象
|
||||||
*/
|
*/
|
||||||
public ObjectMapper getMapper() {
|
@Override
|
||||||
|
public ObjectMapper getRaw() {
|
||||||
initEngine();
|
initEngine();
|
||||||
return mapper;
|
return mapper;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2024 Hutool Team and hutool.cn
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.dromara.hutool.json.serialize;
|
||||||
|
|
||||||
|
import org.dromara.hutool.json.JSONPrimitive;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 原始对象的序列化接口,用于将特定对象序列化为{@link JSONPrimitive}
|
||||||
|
*
|
||||||
|
* @param <V> 对象类型
|
||||||
|
* @author Looly
|
||||||
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface JSONPrimitiveSerializer<V> extends JSONSerializer<JSONPrimitive, V> {
|
||||||
|
}
|
@ -16,36 +16,41 @@
|
|||||||
|
|
||||||
package org.dromara.hutool.json;
|
package org.dromara.hutool.json;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Assertions;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
public class IssueI6LBZATest {
|
public class IssueI6LBZATest {
|
||||||
@Test
|
@Test
|
||||||
public void parseJSONStringTest() {
|
public void parseJSONStringTest() {
|
||||||
final String a = "\"a\"";
|
final String a = "\"a\"";
|
||||||
final Object parse = JSONUtil.parse(a);
|
final Object parse = JSONUtil.parse(a);
|
||||||
Assertions.assertEquals(String.class, parse.getClass());
|
assertEquals(JSONPrimitive.class, parse.getClass());
|
||||||
|
assertEquals(a, parse.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void parseJSONStringTest2() {
|
public void parseJSONStringTest2() {
|
||||||
final String a = "'a'";
|
final String a = "'a'";
|
||||||
final Object parse = JSONUtil.parse(a);
|
final Object parse = JSONUtil.parse(a);
|
||||||
Assertions.assertEquals(String.class, parse.getClass());
|
assertEquals(JSONPrimitive.class, parse.getClass());
|
||||||
|
assertEquals("\"a\"", parse.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void parseJSONErrorTest() {
|
public void parseJSONErrorTest() {
|
||||||
final String a = "a";
|
final String a = "a";
|
||||||
final Object parse = JSONUtil.parse(a);
|
final Object parse = JSONUtil.parse(a);
|
||||||
Assertions.assertEquals(String.class, parse.getClass());
|
assertEquals(JSONPrimitive.class, parse.getClass());
|
||||||
Assertions.assertEquals("\"a\"", parse);
|
assertEquals("\"a\"", parse.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void parseJSONNumberTest() {
|
public void parseJSONNumberTest() {
|
||||||
final String a = "123";
|
final String a = "123";
|
||||||
final Object parse = JSONUtil.parse(a);
|
final JSON parse = JSONUtil.parse(a);
|
||||||
Assertions.assertEquals(Integer.class, parse.getClass());
|
assertEquals(JSONPrimitive.class, parse.getClass());
|
||||||
|
assertEquals(123, ((JSONPrimitive)parse).getValue());
|
||||||
|
assertEquals(Integer.class, ((JSONPrimitive)parse).getValue().getClass());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,8 +59,8 @@ public class IssueI7M2GZTest {
|
|||||||
entity.setList(list);
|
entity.setList(list);
|
||||||
|
|
||||||
final String json = JSONUtil.toJsonStr(entity);
|
final String json = JSONUtil.toJsonStr(entity);
|
||||||
//Console.log(json);
|
|
||||||
final MyEntity<JSONBeanParserImpl> result = JSONUtil.toBean(json, new TypeReference<MyEntity<JSONBeanParserImpl>>() {});
|
final MyEntity<JSONBeanParserImpl> result = JSONUtil.toBean(json, new TypeReference<MyEntity<JSONBeanParserImpl>>() {});
|
||||||
|
|
||||||
Assertions.assertEquals("new Object", result.getList().get(0).getName());
|
Assertions.assertEquals("new Object", result.getList().get(0).getName());
|
||||||
Assertions.assertNotNull(result.getList().get(0).getParsed());
|
Assertions.assertNotNull(result.getList().get(0).getParsed());
|
||||||
Assertions.assertEquals(Integer.valueOf(12), result.getList().get(0).getParsed());
|
Assertions.assertEquals(Integer.valueOf(12), result.getList().get(0).getParsed());
|
||||||
|
@ -53,29 +53,29 @@ public class JSONUtilTest {
|
|||||||
void parseEmptyValue() {
|
void parseEmptyValue() {
|
||||||
// https://www.rfc-editor.org/rfc/rfc8259#section-7
|
// https://www.rfc-editor.org/rfc/rfc8259#section-7
|
||||||
// 未被包装的空串理解为null
|
// 未被包装的空串理解为null
|
||||||
Object parse = JSONUtil.parse("");
|
JSON parse = JSONUtil.parse("");
|
||||||
assertNull(parse);
|
assertNull(parse);
|
||||||
|
|
||||||
parse = JSONUtil.parse("\"\"");
|
parse = JSONUtil.parse("\"\"");
|
||||||
assertEquals("\"\"", parse);
|
assertEquals("\"\"", parse.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void parseValueTest() {
|
public void parseValueTest() {
|
||||||
Object parse = JSONUtil.parse(123);
|
JSON parse = JSONUtil.parse(123);
|
||||||
assertEquals(123, parse);
|
assertEquals(123, ((JSONPrimitive)parse).getValue());
|
||||||
|
|
||||||
parse = JSONUtil.parse("\"abc\"");
|
parse = JSONUtil.parse("\"abc\"");
|
||||||
assertEquals("\"abc\"", parse);
|
assertEquals("\"abc\"", parse.toString());
|
||||||
|
|
||||||
parse = JSONUtil.parse("\"\\\"bc\"");
|
parse = JSONUtil.parse("\"\\\"bc\"");
|
||||||
assertEquals("\"\\\"bc\"", parse);
|
assertEquals("\"\\\"bc\"", parse.toString());
|
||||||
|
|
||||||
parse = JSONUtil.parse("true");
|
parse = JSONUtil.parse("true");
|
||||||
assertEquals(true, parse);
|
assertEquals(true, ((JSONPrimitive)parse).getValue());
|
||||||
|
|
||||||
parse = JSONUtil.parse("False");
|
parse = JSONUtil.parse("False");
|
||||||
assertEquals(false, parse);
|
assertEquals(false, ((JSONPrimitive)parse).getValue());
|
||||||
|
|
||||||
parse = JSONUtil.parse("null");
|
parse = JSONUtil.parse("null");
|
||||||
assertNull(parse);
|
assertNull(parse);
|
||||||
|
@ -23,6 +23,7 @@ import org.junit.jupiter.api.Assertions;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
public class JSONEngineTest {
|
public class JSONEngineTest {
|
||||||
|
|
||||||
@ -43,6 +44,12 @@ public class JSONEngineTest {
|
|||||||
Arrays.stream(engineNames).forEach(this::assertWriteLocalDateFormat);
|
Arrays.stream(engineNames).forEach(this::assertWriteLocalDateFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeTimeZoneTest() {
|
||||||
|
// TODO Hutool无法序列化TimeZone等特殊对象
|
||||||
|
Arrays.stream(engineNames).forEach(this::assertWriteTimeZone);
|
||||||
|
}
|
||||||
|
|
||||||
private void assertWriteDateFormat(final String engineName) {
|
private void assertWriteDateFormat(final String engineName) {
|
||||||
final DateTime date = DateUtil.parse("2024-01-01 01:12:21");
|
final DateTime date = DateUtil.parse("2024-01-01 01:12:21");
|
||||||
final BeanWithDate bean = new BeanWithDate(date, TimeUtil.of(date));
|
final BeanWithDate bean = new BeanWithDate(date, TimeUtil.of(date));
|
||||||
@ -78,4 +85,16 @@ public class JSONEngineTest {
|
|||||||
jsonString = engine.toJsonString(bean);
|
jsonString = engine.toJsonString(bean);
|
||||||
Assertions.assertEquals("{\"date1\":null,\"date2\":null}", jsonString);
|
Assertions.assertEquals("{\"date1\":null,\"date2\":null}", jsonString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void assertWriteTimeZone(final String engineName) {
|
||||||
|
final TimeZone timeZone = TimeZone.getTimeZone("GMT+08:00");
|
||||||
|
final JSONEngine engine = JSONEngineFactory.createEngine(engineName);
|
||||||
|
|
||||||
|
String jsonString = engine.toJsonString(timeZone);
|
||||||
|
Assertions.assertEquals("\"GMT+08:00\"", jsonString);
|
||||||
|
|
||||||
|
engine.init(JSONEngineConfig.of().setIgnoreNullValue(false));
|
||||||
|
jsonString = engine.toJsonString(timeZone);
|
||||||
|
Assertions.assertEquals("\"GMT+08:00\"", jsonString);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user