mirror of
https://gitee.com/dromara/hutool.git
synced 2025-05-03 12:18:01 +08:00
add config
This commit is contained in:
parent
dd7f04af44
commit
f6f97668cf
@ -9,6 +9,7 @@
|
||||
* 【captcha】 AbstractCaptcha增加getImageBase64Data方法(pr#985@Github)
|
||||
* 【core 】 增加PhoneUtil(pr#990@Github)
|
||||
* 【core 】 改进Img,目标图片类型未定义使用源图片类型(issue#I1PB0B@Gitee)
|
||||
* 【json 】 JSONConfig增加Transient选项(issue#I1PLHN@Gitee)
|
||||
|
||||
### Bug修复
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package cn.hutool.core.bean;
|
||||
|
||||
import cn.hutool.core.annotation.AnnotationUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.map.CaseInsensitiveMap;
|
||||
import cn.hutool.core.util.BooleanUtil;
|
||||
@ -9,6 +10,7 @@ import cn.hutool.core.util.ReflectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.util.TypeUtil;
|
||||
|
||||
import java.beans.Transient;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
@ -20,28 +22,32 @@ import java.util.Map;
|
||||
/**
|
||||
* Bean信息描述做为BeanInfo替代方案,此对象持有JavaBean中的setters和getters等相关信息描述<br>
|
||||
* 查找Getter和Setter方法时会:
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* 1. 忽略字段和方法名的大小写
|
||||
* 2. Getter查找getXXX、isXXX、getIsXXX
|
||||
* 3. Setter查找setXXX、setIsXXX
|
||||
* 4. Setter忽略参数值与字段值不匹配的情况,因此有多个参数类型的重载时,会调用首次匹配的
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
* @since 3.1.2
|
||||
*/
|
||||
public class BeanDesc implements Serializable{
|
||||
public class BeanDesc implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** Bean类 */
|
||||
/**
|
||||
* Bean类
|
||||
*/
|
||||
private final Class<?> beanClass;
|
||||
/** 属性Map */
|
||||
/**
|
||||
* 属性Map
|
||||
*/
|
||||
private final Map<String, PropDesc> propMap = new LinkedHashMap<>();
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param beanClass Bean类
|
||||
*/
|
||||
public BeanDesc(Class<?> beanClass) {
|
||||
@ -52,7 +58,7 @@ public class BeanDesc implements Serializable{
|
||||
|
||||
/**
|
||||
* 获取Bean的全类名
|
||||
*
|
||||
*
|
||||
* @return Bean的类名
|
||||
*/
|
||||
public String getName() {
|
||||
@ -61,7 +67,7 @@ public class BeanDesc implements Serializable{
|
||||
|
||||
/**
|
||||
* 获取Bean的简单类名
|
||||
*
|
||||
*
|
||||
* @return Bean的类名
|
||||
*/
|
||||
public String getSimpleName() {
|
||||
@ -70,7 +76,7 @@ public class BeanDesc implements Serializable{
|
||||
|
||||
/**
|
||||
* 获取字段名-字段属性Map
|
||||
*
|
||||
*
|
||||
* @param ignoreCase 是否忽略大小写,true为忽略,false不忽略
|
||||
* @return 字段名-字段属性Map
|
||||
*/
|
||||
@ -80,7 +86,7 @@ public class BeanDesc implements Serializable{
|
||||
|
||||
/**
|
||||
* 获取字段属性列表
|
||||
*
|
||||
*
|
||||
* @return {@link PropDesc} 列表
|
||||
*/
|
||||
public Collection<PropDesc> getProps() {
|
||||
@ -89,7 +95,7 @@ public class BeanDesc implements Serializable{
|
||||
|
||||
/**
|
||||
* 获取属性,如果不存在返回null
|
||||
*
|
||||
*
|
||||
* @param fieldName 字段名
|
||||
* @return {@link PropDesc}
|
||||
*/
|
||||
@ -99,7 +105,7 @@ public class BeanDesc implements Serializable{
|
||||
|
||||
/**
|
||||
* 获得字段名对应的字段对象,如果不存在返回null
|
||||
*
|
||||
*
|
||||
* @param fieldName 字段名
|
||||
* @return 字段值
|
||||
*/
|
||||
@ -110,7 +116,7 @@ public class BeanDesc implements Serializable{
|
||||
|
||||
/**
|
||||
* 获取Getter方法,如果不存在返回null
|
||||
*
|
||||
*
|
||||
* @param fieldName 字段名
|
||||
* @return Getter方法
|
||||
*/
|
||||
@ -121,7 +127,7 @@ public class BeanDesc implements Serializable{
|
||||
|
||||
/**
|
||||
* 获取Setter方法,如果不存在返回null
|
||||
*
|
||||
*
|
||||
* @param fieldName 字段名
|
||||
* @return Setter方法
|
||||
*/
|
||||
@ -129,17 +135,18 @@ public class BeanDesc implements Serializable{
|
||||
final PropDesc desc = this.propMap.get(fieldName);
|
||||
return null == desc ? null : desc.getSetter();
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------ Private method start
|
||||
|
||||
/**
|
||||
* 初始化<br>
|
||||
* 只有与属性关联的相关Getter和Setter方法才会被读取,无关的getXXX和setXXX都被忽略
|
||||
*
|
||||
*
|
||||
* @return this
|
||||
*/
|
||||
private BeanDesc init() {
|
||||
for (Field field : ReflectUtil.getFields(this.beanClass)) {
|
||||
if(false == ModifierUtil.isStatic(field)) {
|
||||
if (false == ModifierUtil.isStatic(field)) {
|
||||
//只针对非static属性
|
||||
this.propMap.put(ReflectUtil.getFieldName(field), createProp(field));
|
||||
}
|
||||
@ -150,14 +157,14 @@ public class BeanDesc implements Serializable{
|
||||
/**
|
||||
* 根据字段创建属性描述<br>
|
||||
* 查找Getter和Setter方法时会:
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* 1. 忽略字段和方法名的大小写
|
||||
* 2. Getter查找getXXX、isXXX、getIsXXX
|
||||
* 3. Setter查找setXXX、setIsXXX
|
||||
* 4. Setter忽略参数值与字段值不匹配的情况,因此有多个参数类型的重载时,会调用首次匹配的
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @param field 字段
|
||||
* @return {@link PropDesc}
|
||||
* @since 4.0.2
|
||||
@ -201,7 +208,7 @@ public class BeanDesc implements Serializable{
|
||||
/**
|
||||
* 方法是否为Getter方法<br>
|
||||
* 匹配规则如下(忽略大小写):
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* 字段名 -》 方法名
|
||||
* isName -》 isName
|
||||
@ -210,9 +217,9 @@ public class BeanDesc implements Serializable{
|
||||
* name -》 isName
|
||||
* name -》 getName
|
||||
* </pre>
|
||||
*
|
||||
* @param methodName 方法名
|
||||
* @param fieldName 字段名
|
||||
*
|
||||
* @param methodName 方法名
|
||||
* @param fieldName 字段名
|
||||
* @param isBooeanField 是否为Boolean类型字段
|
||||
* @return 是否匹配
|
||||
*/
|
||||
@ -225,7 +232,7 @@ public class BeanDesc implements Serializable{
|
||||
// 非标准Getter方法
|
||||
return false;
|
||||
}
|
||||
if("getclass".equals(methodName)) {
|
||||
if ("getclass".equals(methodName)) {
|
||||
//跳过getClass方法
|
||||
return false;
|
||||
}
|
||||
@ -253,16 +260,16 @@ public class BeanDesc implements Serializable{
|
||||
/**
|
||||
* 方法是否为Setter方法<br>
|
||||
* 匹配规则如下(忽略大小写):
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* 字段名 -》 方法名
|
||||
* isName -》 setName
|
||||
* isName -》 setIsName
|
||||
* name -》 setName
|
||||
* </pre>
|
||||
*
|
||||
* @param methodName 方法名
|
||||
* @param fieldName 字段名
|
||||
*
|
||||
* @param methodName 方法名
|
||||
* @param fieldName 字段名
|
||||
* @param isBooeanField 是否为Boolean类型字段
|
||||
* @return 是否匹配
|
||||
*/
|
||||
@ -293,24 +300,29 @@ public class BeanDesc implements Serializable{
|
||||
|
||||
/**
|
||||
* 属性描述
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
* @author looly
|
||||
*/
|
||||
public static class PropDesc {
|
||||
|
||||
/** 字段 */
|
||||
/**
|
||||
* 字段
|
||||
*/
|
||||
private final Field field;
|
||||
/** Getter方法 */
|
||||
/**
|
||||
* Getter方法
|
||||
*/
|
||||
private final Method getter;
|
||||
/** Setter方法 */
|
||||
/**
|
||||
* Setter方法
|
||||
*/
|
||||
private final Method setter;
|
||||
|
||||
/**
|
||||
* 构造<br>
|
||||
* Getter和Setter方法设置为默认可访问
|
||||
*
|
||||
* @param field 字段
|
||||
*
|
||||
* @param field 字段
|
||||
* @param getter get方法
|
||||
* @param setter set方法
|
||||
*/
|
||||
@ -322,7 +334,7 @@ public class BeanDesc implements Serializable{
|
||||
|
||||
/**
|
||||
* 获取字段名,如果存在Alias注解,读取注解的值作为名称
|
||||
*
|
||||
*
|
||||
* @return 字段名
|
||||
*/
|
||||
public String getFieldName() {
|
||||
@ -341,7 +353,7 @@ public class BeanDesc implements Serializable{
|
||||
|
||||
/**
|
||||
* 获取字段
|
||||
*
|
||||
*
|
||||
* @return 字段
|
||||
*/
|
||||
public Field getField() {
|
||||
@ -351,7 +363,7 @@ public class BeanDesc implements Serializable{
|
||||
/**
|
||||
* 获得字段类型<br>
|
||||
* 先获取字段的类型,如果字段不存在,则获取Getter方法的返回类型,否则获取Setter的第一个参数类型
|
||||
*
|
||||
*
|
||||
* @return 字段类型
|
||||
*/
|
||||
public Type getFieldType() {
|
||||
@ -364,7 +376,7 @@ public class BeanDesc implements Serializable{
|
||||
/**
|
||||
* 获得字段类型<br>
|
||||
* 先获取字段的类型,如果字段不存在,则获取Getter方法的返回类型,否则获取Setter的第一个参数类型
|
||||
*
|
||||
*
|
||||
* @return 字段类型
|
||||
*/
|
||||
public Class<?> getFieldClass() {
|
||||
@ -376,7 +388,7 @@ public class BeanDesc implements Serializable{
|
||||
|
||||
/**
|
||||
* 获取Getter方法,可能为{@code null}
|
||||
*
|
||||
*
|
||||
* @return Getter方法
|
||||
*/
|
||||
public Method getGetter() {
|
||||
@ -385,52 +397,75 @@ public class BeanDesc implements Serializable{
|
||||
|
||||
/**
|
||||
* 获取Setter方法,可能为{@code null}
|
||||
*
|
||||
*
|
||||
* @return {@link Method}Setter 方法对象
|
||||
*/
|
||||
public Method getSetter() {
|
||||
return this.setter;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取字段值<br>
|
||||
* 首先调用字段对应的Getter方法获取值,如果Getter方法不存在,则判断字段如果为public,则直接获取字段值
|
||||
*
|
||||
*
|
||||
* @param bean Bean对象
|
||||
* @return 字段值
|
||||
* @since 4.0.5
|
||||
*/
|
||||
public Object getValue(Object bean) {
|
||||
if(null != this.getter) {
|
||||
if (null != this.getter) {
|
||||
return ReflectUtil.invoke(bean, this.getter);
|
||||
} else if(ModifierUtil.isPublic(this.field)) {
|
||||
} else if (ModifierUtil.isPublic(this.field)) {
|
||||
return ReflectUtil.getFieldValue(bean, this.field);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置Bean的字段值<br>
|
||||
* 首先调用字段对应的Setter方法,如果Setter方法不存在,则判断字段如果为public,则直接赋值字段值
|
||||
*
|
||||
* @param bean Bean对象
|
||||
*
|
||||
* @param bean Bean对象
|
||||
* @param value 值
|
||||
* @return this
|
||||
* @since 4.0.5
|
||||
*/
|
||||
public PropDesc setValue(Object bean, Object value) {
|
||||
if(null != this.setter) {
|
||||
if (null != this.setter) {
|
||||
ReflectUtil.invoke(bean, this.setter, value);
|
||||
} else if(ModifierUtil.isPublic(this.field)) {
|
||||
} else if (ModifierUtil.isPublic(this.field)) {
|
||||
ReflectUtil.setFieldValue(bean, this.field, value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 字段和Getter方法是否为Transient关键字修饰的
|
||||
*
|
||||
* @return 是否为Transient关键字修饰的
|
||||
* @since 5.3.11
|
||||
*/
|
||||
public boolean isTransient() {
|
||||
boolean isTransient = ModifierUtil.hasModifier(this.field, ModifierUtil.ModifierType.TRANSIENT);
|
||||
|
||||
// 检查Getter方法
|
||||
if(false == isTransient && null != this.getter){
|
||||
isTransient = ModifierUtil.hasModifier(this.getter, ModifierUtil.ModifierType.TRANSIENT);
|
||||
|
||||
// 检查注解
|
||||
if(false == isTransient){
|
||||
isTransient = null != AnnotationUtil.getAnnotation(this.getter, Transient.class);
|
||||
}
|
||||
}
|
||||
|
||||
return isTransient;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------ Private method start
|
||||
|
||||
/**
|
||||
* 通过Getter和Setter方法中找到属性类型
|
||||
*
|
||||
*
|
||||
* @param getter Getter方法
|
||||
* @param setter Setter方法
|
||||
* @return {@link Type}
|
||||
@ -448,7 +483,7 @@ public class BeanDesc implements Serializable{
|
||||
|
||||
/**
|
||||
* 通过Getter和Setter方法中找到属性类型
|
||||
*
|
||||
*
|
||||
* @param getter Getter方法
|
||||
* @param setter Setter方法
|
||||
* @return {@link Type}
|
||||
|
@ -4,26 +4,41 @@ import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* JSON配置项
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
* @since 4.1.19
|
||||
*/
|
||||
public class JSONConfig implements Serializable {
|
||||
private static final long serialVersionUID = 119730355204738278L;
|
||||
|
||||
/** 是否有序,顺序按照加入顺序排序 */
|
||||
/**
|
||||
* 是否有序,顺序按照加入顺序排序
|
||||
*/
|
||||
private boolean order;
|
||||
/** 是否忽略转换过程中的异常 */
|
||||
/**
|
||||
* 是否忽略转换过程中的异常
|
||||
*/
|
||||
private boolean ignoreError;
|
||||
/** 是否忽略键的大小写 */
|
||||
/**
|
||||
* 是否忽略键的大小写
|
||||
*/
|
||||
private boolean ignoreCase;
|
||||
/** 日期格式,null表示默认的时间戳 */
|
||||
/**
|
||||
* 日期格式,null表示默认的时间戳
|
||||
*/
|
||||
private String dateFormat;
|
||||
/** 是否忽略null值 */
|
||||
/**
|
||||
* 是否忽略null值
|
||||
*/
|
||||
private boolean ignoreNullValue = true;
|
||||
|
||||
/**
|
||||
* 是否忽略transient关键字修饰的字段
|
||||
*/
|
||||
private boolean ignoreTransient = true;
|
||||
|
||||
/**
|
||||
* 创建默认的配置项
|
||||
*
|
||||
* @return JSONConfig
|
||||
*/
|
||||
public static JSONConfig create() {
|
||||
@ -32,7 +47,7 @@ public class JSONConfig implements Serializable {
|
||||
|
||||
/**
|
||||
* 是否有序,顺序按照加入顺序排序
|
||||
*
|
||||
*
|
||||
* @return 是否有序
|
||||
*/
|
||||
public boolean isOrder() {
|
||||
@ -41,7 +56,7 @@ public class JSONConfig implements Serializable {
|
||||
|
||||
/**
|
||||
* 设置是否有序,顺序按照加入顺序排序
|
||||
*
|
||||
*
|
||||
* @param order 是否有序
|
||||
* @return this
|
||||
*/
|
||||
@ -52,7 +67,7 @@ public class JSONConfig implements Serializable {
|
||||
|
||||
/**
|
||||
* 是否忽略转换过程中的异常
|
||||
*
|
||||
*
|
||||
* @return 是否忽略转换过程中的异常
|
||||
*/
|
||||
public boolean isIgnoreError() {
|
||||
@ -61,7 +76,7 @@ public class JSONConfig implements Serializable {
|
||||
|
||||
/**
|
||||
* 设置是否忽略转换过程中的异常
|
||||
*
|
||||
*
|
||||
* @param ignoreError 是否忽略转换过程中的异常
|
||||
* @return this
|
||||
*/
|
||||
@ -72,7 +87,7 @@ public class JSONConfig implements Serializable {
|
||||
|
||||
/**
|
||||
* 是否忽略键的大小写
|
||||
*
|
||||
*
|
||||
* @return 是否忽略键的大小写
|
||||
*/
|
||||
public boolean isIgnoreCase() {
|
||||
@ -81,7 +96,7 @@ public class JSONConfig implements Serializable {
|
||||
|
||||
/**
|
||||
* 设置是否忽略键的大小写
|
||||
*
|
||||
*
|
||||
* @param ignoreCase 是否忽略键的大小写
|
||||
* @return this
|
||||
*/
|
||||
@ -92,7 +107,7 @@ public class JSONConfig implements Serializable {
|
||||
|
||||
/**
|
||||
* 日期格式,null表示默认的时间戳
|
||||
*
|
||||
*
|
||||
* @return 日期格式,null表示默认的时间戳
|
||||
*/
|
||||
public String getDateFormat() {
|
||||
@ -101,7 +116,7 @@ public class JSONConfig implements Serializable {
|
||||
|
||||
/**
|
||||
* 设置日期格式,null表示默认的时间戳
|
||||
*
|
||||
*
|
||||
* @param dateFormat 日期格式,null表示默认的时间戳
|
||||
* @return this
|
||||
*/
|
||||
@ -109,10 +124,10 @@ public class JSONConfig implements Serializable {
|
||||
this.dateFormat = dateFormat;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 是否忽略null值
|
||||
*
|
||||
*
|
||||
* @return 是否忽略null值
|
||||
*/
|
||||
public boolean isIgnoreNullValue() {
|
||||
@ -121,7 +136,7 @@ public class JSONConfig implements Serializable {
|
||||
|
||||
/**
|
||||
* 设置是否忽略null值
|
||||
*
|
||||
*
|
||||
* @param ignoreNullValue 是否忽略null值
|
||||
* @return this
|
||||
*/
|
||||
@ -129,4 +144,26 @@ public class JSONConfig implements Serializable {
|
||||
this.ignoreNullValue = ignoreNullValue;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否忽略transient关键字修饰的字段
|
||||
*
|
||||
* @return 是否忽略transient关键字修饰的字段
|
||||
* @since 5.3.11
|
||||
*/
|
||||
public boolean isIgnoreTransient() {
|
||||
return this.ignoreTransient;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置是否忽略transient关键字修饰的字段
|
||||
*
|
||||
* @param ignoreTransient 是否忽略transient关键字修饰的字段
|
||||
* @return this
|
||||
* @since 5.3.11
|
||||
*/
|
||||
public JSONConfig setIgnoreTransient(boolean ignoreTransient) {
|
||||
this.ignoreTransient = ignoreTransient;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
@ -625,6 +625,11 @@ public class JSONObject implements JSON, JSONGetter<String>, Map<String, Object>
|
||||
Method getter;
|
||||
Object value;
|
||||
for (PropDesc prop : props) {
|
||||
if(this.config.isIgnoreTransient() && prop.isTransient()){
|
||||
// 忽略Transient字段和方法
|
||||
continue;
|
||||
}
|
||||
|
||||
// 得到property对应的getter方法
|
||||
getter = prop.getGetter();
|
||||
if (null == getter) {
|
||||
|
25
hutool-json/src/test/java/cn/hutool/json/TransientTest.java
Normal file
25
hutool-json/src/test/java/cn/hutool/json/TransientTest.java
Normal file
@ -0,0 +1,25 @@
|
||||
package cn.hutool.json;
|
||||
|
||||
import lombok.Data;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class TransientTest {
|
||||
|
||||
@Data
|
||||
static class Bill{
|
||||
private transient String id;
|
||||
private String bizNo;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beanWithTransientTest(){
|
||||
Bill detailBill = new Bill();
|
||||
detailBill.setId("3243");
|
||||
detailBill.setBizNo("bizNo");
|
||||
|
||||
final JSONObject jsonObject = new JSONObject(detailBill,
|
||||
JSONConfig.create().setIgnoreTransient(true));
|
||||
Assert.assertEquals("{\"bizNo\":\"bizNo\"}", jsonObject.toString());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user