add methods

This commit is contained in:
Looly 2020-09-08 23:41:00 +08:00
parent 2212ee7705
commit 46764f02b8
12 changed files with 324 additions and 140 deletions

View File

@ -18,6 +18,7 @@
* 【core 】 TypeUtil增加getActualType增加ActualTypeMapperPool类issue#I1TBWH@Gitee
* 【extra 】 QRConfig中添加qrVersion属性pr#1068@Github
* 【core 】 ArrayUtil增加equals方法
* 【core 】 BeanDesc增加方法
### Bug修复
* 【core 】 重新整理农历节假日解决一个pr过来的玩笑导致的问题

View File

@ -61,6 +61,18 @@ public class AnnotationUtil {
return (null == annotationEle) ? null : toCombination(annotationEle).getAnnotation(annotationType);
}
/**
* 检查是否包含指定注解指定注解
*
* @param annotationEle {@link AnnotatedElement}可以是ClassMethodFieldConstructorReflectPermission
* @param annotationType 注解类型
* @return 是否包含指定注解
* @since 5.4.2
*/
public static boolean hasAnnotation(AnnotatedElement annotationEle, Class<? extends Annotation> annotationType) {
return null != getAnnotation(annotationEle, annotationType);
}
/**
* 获取指定注解默认值<br>
* 如果无指定的属性方法返回null

View File

@ -0,0 +1,20 @@
package cn.hutool.core.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 忽略注解使用此注解的字段等会被忽略主要用于Bean拷贝Bean转Map等
*
* @author Looly
* @since 5.4.2
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
public @interface Ignore {
}

View File

@ -1,6 +1,8 @@
package cn.hutool.core.bean;
import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.annotation.Ignore;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.CaseInsensitiveMap;
import cn.hutool.core.util.BooleanUtil;
@ -439,7 +441,7 @@ public class BeanDesc implements Serializable {
}
/**
* 获取字段<br>
* 获取属性<br>
* 首先调用字段对应的Getter方法获取值如果Getter方法不存在则判断字段如果为public则直接获取字段值
*
* @param bean Bean对象
@ -455,12 +457,42 @@ public class BeanDesc implements Serializable {
return null;
}
/**
* 获取属性值自动转换属性值类型<br>
* 首先调用字段对应的Getter方法获取值如果Getter方法不存在则判断字段如果为public则直接获取字段值
*
* @param bean Bean对象
* @param valueType 返回属性值类型null表示不转换
* @param ignoreError 是否忽略错误包括转换错误和注入错误
* @return this
* @since 5.4.2
*/
public Object getValueWithConvert(Object bean, Type valueType, boolean ignoreError) {
Object result = null;
try {
result = getValue(bean);
} catch (Exception e) {
if (false == ignoreError) {
throw new BeanException(e, "Get value of [{}] error!", getFieldName());
}
}
if (null != result && null != valueType) {
// 尝试将结果转换为目标类型如果转换失败返回原类型
final Object convertValue = Convert.convertWithCheck(valueType, result, null, ignoreError);
if (null != convertValue) {
result = convertValue;
}
}
return result;
}
/**
* 设置Bean的字段值<br>
* 首先调用字段对应的Setter方法如果Setter方法不存在则判断字段如果为public则直接赋值字段值
*
* @param bean Bean对象
* @param value
* @param value 必须与字段值类型匹配
* @return this
* @since 4.0.5
*/
@ -473,6 +505,44 @@ public class BeanDesc implements Serializable {
return this;
}
/**
* 设置属性值可以自动转换字段类型为目标类型
*
* @param bean Bean对象
* @param value 属性值可以为任意类型
* @param ignoreNull 是否忽略{@code null}true表示忽略
* @param ignoreError 是否忽略错误包括转换错误和注入错误
* @return this
* @since 5.4.2
*/
public PropDesc setValueWithConvert(Object bean, Object value, boolean ignoreNull, boolean ignoreError) {
if (ignoreNull && null == value) {
return this;
}
// 当类型不匹配的时候执行默认转换
if (null != value) {
final Class<?> propClass = getFieldClass();
if (false == propClass.isInstance(value)) {
value = Convert.convertWithCheck(propClass, value, null, ignoreError);
}
}
// 属性赋值
if (null != value || false == ignoreNull) {
try {
this.setValue(bean, value);
} catch (Exception e) {
if (false == ignoreError) {
throw new BeanException(e, "Set value of [{}] error!", getFieldName());
}
// 忽略注入失败
}
}
return this;
}
/**
* 字段和Getter方法是否为Transient关键字修饰的
*
@ -488,13 +558,43 @@ public class BeanDesc implements Serializable {
// 检查注解
if (false == isTransient) {
isTransient = null != AnnotationUtil.getAnnotation(this.getter, Transient.class);
isTransient = AnnotationUtil.hasAnnotation(this.getter, Transient.class);
}
}
return isTransient;
}
/**
* 检查字段是否被忽略读通过{@link Ignore} 注解完成规则为
* <pre>
* 1. 在字段上有{@link Ignore} 注解
* 2. 在getXXX方法上有{@link Ignore} 注解
* </pre>
*
* @return 是否忽略读
* @since 5.4.2
*/
public boolean isIgnoreGet() {
return AnnotationUtil.hasAnnotation(this.field, Ignore.class)
|| AnnotationUtil.hasAnnotation(this.getter, Ignore.class);
}
/**
* 检查字段是否被忽略写通过{@link Ignore} 注解完成规则为
* <pre>
* 1. 在字段上有{@link Ignore} 注解
* 2. 在setXXX方法上有{@link Ignore} 注解
* </pre>
*
* @return 是否忽略写
* @since 5.4.2
*/
public boolean isIgnoreSet() {
return AnnotationUtil.hasAnnotation(this.field, Ignore.class)
|| AnnotationUtil.hasAnnotation(this.setter, Ignore.class);
}
//------------------------------------------------------------------------------------ Private method start
/**

View File

@ -1,6 +1,7 @@
package cn.hutool.core.bean;
import cn.hutool.core.lang.SimpleCache;
import cn.hutool.core.lang.func.Func0;
/**
* Bean属性缓存<br>
@ -16,18 +17,11 @@ public enum BeanDescCache {
/**
* 获得属性名和{@link BeanDesc}Map映射
* @param beanClass Bean的类
* @param supplier 对象不存在时创建对象的函数
* @return 属性名和{@link BeanDesc}映射
* @since 5.4.2
*/
public BeanDesc getBeanDesc(Class<?> beanClass){
return bdCache.get(beanClass);
}
/**
* 加入缓存
* @param beanClass Bean的类
* @param BeanDesc 属性名和{@link BeanDesc}映射
*/
public void putBeanDesc(Class<?> beanClass, BeanDesc BeanDesc){
bdCache.put(beanClass, BeanDesc);
public BeanDesc getBeanDesc(Class<?> beanClass, Func0<BeanDesc> supplier){
return bdCache.get(beanClass, supplier);
}
}

View File

@ -166,12 +166,7 @@ public class BeanUtil {
* @since 3.1.2
*/
public static BeanDesc getBeanDesc(Class<?> clazz) {
BeanDesc beanDesc = BeanDescCache.INSTANCE.getBeanDesc(clazz);
if (null == beanDesc) {
beanDesc = new BeanDesc(clazz);
BeanDescCache.INSTANCE.putBeanDesc(clazz, beanDesc);
}
return beanDesc;
return BeanDescCache.INSTANCE.getBeanDesc(clazz, ()-> new BeanDesc(clazz));
}
// --------------------------------------------------------------------------------------------------------- PropertyDescriptor

View File

@ -1,12 +1,11 @@
package cn.hutool.core.bean.copier;
import cn.hutool.core.bean.BeanDesc.PropDesc;
import cn.hutool.core.bean.BeanException;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.provider.BeanValueProvider;
import cn.hutool.core.bean.copier.provider.MapValueProvider;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.lang.copier.Copier;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ModifierUtil;
@ -23,7 +22,14 @@ import java.util.HashSet;
import java.util.Map;
/**
* Bean拷贝
* Bean拷贝提供
*
* <pre>
* 1. Bean Bean
* 2. Bean Map
* 3. Map Bean
* 4. Map Map
* </pre>
*
* @author looly
*
@ -158,36 +164,33 @@ public class BeanCopier<T> implements Copier<T>, Serializable {
final CopyOptions copyOptions = this.copyOptions;
String key;
Method getter;
Object value;
for (PropDesc prop : props) {
key = prop.getFieldName();
// 过滤class属性
// 得到property对应的getter方法
getter = prop.getGetter();
if (null != getter) {
// 只读取有getter方法的属性
try {
value = getter.invoke(bean);
} catch (Exception e) {
if (copyOptions.ignoreError) {
continue;// 忽略反射失败
} else {
throw new UtilException(e, "Get value of [{}] error!", prop.getFieldName());
}
}
if (CollUtil.contains(ignoreSet, key)) {
// 目标属性值被忽略或值提供者无此key时跳过
continue;
}
if (null == value && copyOptions.ignoreNullValue) {
continue;// 当允许跳过空时跳过
}
if (bean.equals(value)) {
continue;// 值不能为bean本身防止循环引用
}
targetMap.put(mappingKey(copyOptions.fieldMapping, key), value);
// 忽略注解的字段
if(prop.isIgnoreGet()){
continue;
}
key = prop.getFieldName();
if (CollUtil.contains(ignoreSet, key)) {
// 目标属性值被忽略或值提供者无此key时跳过
continue;
}
try {
value = prop.getValue(bean);
} catch (Exception e) {
if (copyOptions.ignoreError) {
continue;// 忽略反射失败
} else {
throw new BeanException(e, "Get value of [{}] error!", prop.getFieldName());
}
}
if (null == value && copyOptions.ignoreNullValue) {
continue;// 当允许跳过空时跳过
}
if (bean.equals(value)) {
continue;// 值不能为bean本身防止循环引用
}
targetMap.put(mappingKey(copyOptions.fieldMapping, key), value);
}
}
@ -228,6 +231,17 @@ public class BeanCopier<T> implements Copier<T>, Serializable {
// 目标属性值被忽略或值提供者无此key时跳过
continue;
}
// 在支持情况下忽略transient修饰包括修饰和注解
if(copyOptions.isTransientSupport() && prop.isTransient()){
continue;
}
// @Ignore修饰的字段和setXXX方法忽略之
if(prop.isIgnoreSet()){
continue;
}
final String providerKey = mappingKey(fieldReverseMapping, fieldName);
if (false == valueProvider.containsKey(providerKey)) {
// 无对应值可提供
@ -241,34 +255,18 @@ public class BeanCopier<T> implements Copier<T>, Serializable {
}
// 获取目标字段真实类型
Type fieldType = (null == setterMethod) ? TypeUtil.getType(field) : TypeUtil.getFirstParamType(setterMethod);
fieldType = TypeUtil.getActualType(this.destType ,fieldType);
final Type fieldType = TypeUtil.getActualType(this.destType ,prop.getFieldType());
value = valueProvider.value(providerKey, fieldType);
if (null == value && copyOptions.ignoreNullValue) {
continue;// 当允许跳过空时跳过
}
if (bean == value) {
continue;// 值不能为bean本身防止循环引用
// 值不能为bean本身防止循环引用
continue;
}
try {
// valueProvider在没有对值做转换且当类型不匹配的时候执行默认转换
propClass = prop.getFieldClass();
if (false ==propClass.isInstance(value)) {
value = Convert.convertWithCheck(propClass, value, null, copyOptions.ignoreError);
if (null == value && copyOptions.ignoreNullValue) {
continue;// 当允许跳过空时跳过
}
}
prop.setValue(bean, value);
} catch (Exception e) {
if (false ==copyOptions.ignoreError) {
throw new UtilException(e, "Inject [{}] error!", prop.getFieldName());
}
// 忽略注入失败
}
prop.setValueWithConvert(bean, value, copyOptions.ignoreNullValue, copyOptions.ignoreError);
}
}

View File

@ -1,38 +1,54 @@
package cn.hutool.core.bean.copier;
import cn.hutool.core.map.MapUtil;
import java.io.Serializable;
import java.util.Map;
import cn.hutool.core.map.MapUtil;
/**
* 属性拷贝选项<br>
* 包括<br>
* 1限制的类或接口必须为目标对象的实现接口或父类用于限制拷贝的属性例如一个类我只想复制其父类的一些属性就可以将editable设置为父类<br>
* 2是否忽略空值当源对象的值为null时true: 忽略而不注入此值false: 注入null<br>
* 3忽略的属性列表设置一个属性列表不拷贝这些属性值<br>
*
*
* @author Looly
*/
public class CopyOptions implements Serializable{
public class CopyOptions implements Serializable {
private static final long serialVersionUID = 1L;
/** 限制的类或接口必须为目标对象的实现接口或父类用于限制拷贝的属性例如一个类我只想复制其父类的一些属性就可以将editable设置为父类 */
/**
* 限制的类或接口必须为目标对象的实现接口或父类用于限制拷贝的属性例如一个类我只想复制其父类的一些属性就可以将editable设置为父类
*/
protected Class<?> editable;
/** 是否忽略空值当源对象的值为null时true: 忽略而不注入此值false: 注入null */
/**
* 是否忽略空值当源对象的值为null时true: 忽略而不注入此值false: 注入null
*/
protected boolean ignoreNullValue;
/** 忽略的目标对象中属性列表,设置一个属性列表,不拷贝这些属性值 */
/**
* 忽略的目标对象中属性列表设置一个属性列表不拷贝这些属性值
*/
protected String[] ignoreProperties;
/** 是否忽略字段注入错误 */
/**
* 是否忽略字段注入错误
*/
protected boolean ignoreError;
/** 是否忽略字段大小写 */
/**
* 是否忽略字段大小写
*/
protected boolean ignoreCase;
/** 拷贝属性的字段映射,用于不同的属性之前拷贝做对应表用 */
/**
* 拷贝属性的字段映射用于不同的属性之前拷贝做对应表用
*/
protected Map<String, String> fieldMapping;
/**
* 是否支持transient关键字修饰和@Transient注解如果支持被修饰的字段或方法对应的字段将被忽略
*/
private boolean transientSupport = true;
/**
* 创建拷贝选项
*
*
* @return 拷贝选项
*/
public static CopyOptions create() {
@ -41,9 +57,9 @@ public class CopyOptions implements Serializable{
/**
* 创建拷贝选项
*
* @param editable 限制的类或接口必须为目标对象的实现接口或父类用于限制拷贝的属性
* @param ignoreNullValue 是否忽略空值当源对象的值为null时true: 忽略而不注入此值false: 注入null
*
* @param editable 限制的类或接口必须为目标对象的实现接口或父类用于限制拷贝的属性
* @param ignoreNullValue 是否忽略空值当源对象的值为null时true: 忽略而不注入此值false: 注入null
* @param ignoreProperties 忽略的属性列表设置一个属性列表不拷贝这些属性值
* @return 拷贝选项
*/
@ -59,9 +75,9 @@ public class CopyOptions implements Serializable{
/**
* 构造拷贝选项
*
* @param editable 限制的类或接口必须为目标对象的实现接口或父类用于限制拷贝的属性
* @param ignoreNullValue 是否忽略空值当源对象的值为null时true: 忽略而不注入此值false: 注入null
*
* @param editable 限制的类或接口必须为目标对象的实现接口或父类用于限制拷贝的属性
* @param ignoreNullValue 是否忽略空值当源对象的值为null时true: 忽略而不注入此值false: 注入null
* @param ignoreProperties 忽略的目标对象中属性列表设置一个属性列表不拷贝这些属性值
*/
public CopyOptions(Class<?> editable, boolean ignoreNullValue, String... ignoreProperties) {
@ -72,7 +88,7 @@ public class CopyOptions implements Serializable{
/**
* 设置限制的类或接口必须为目标对象的实现接口或父类用于限制拷贝的属性
*
*
* @param editable 限制的类或接口
* @return CopyOptions
*/
@ -83,7 +99,7 @@ public class CopyOptions implements Serializable{
/**
* 设置是否忽略空值当源对象的值为null时true: 忽略而不注入此值false: 注入null
*
*
* @param ignoreNullVall 是否忽略空值当源对象的值为null时true: 忽略而不注入此值false: 注入null
* @return CopyOptions
*/
@ -91,10 +107,10 @@ public class CopyOptions implements Serializable{
this.ignoreNullValue = ignoreNullVall;
return this;
}
/**
* 设置忽略空值当源对象的值为null时忽略而不注入此值
*
*
* @return CopyOptions
* @since 4.5.7
*/
@ -104,7 +120,7 @@ public class CopyOptions implements Serializable{
/**
* 设置忽略的目标对象中属性列表设置一个属性列表不拷贝这些属性值
*
*
* @param ignoreProperties 忽略的目标对象中属性列表设置一个属性列表不拷贝这些属性值
* @return CopyOptions
*/
@ -115,7 +131,7 @@ public class CopyOptions implements Serializable{
/**
* 设置是否忽略字段的注入错误
*
*
* @param ignoreError 是否忽略注入错误
* @return CopyOptions
*/
@ -123,20 +139,20 @@ public class CopyOptions implements Serializable{
this.ignoreError = ignoreError;
return this;
}
/**
* 设置忽略字段的注入错误
*
*
* @return CopyOptions
* @since 4.5.7
*/
public CopyOptions ignoreError() {
return setIgnoreError(true);
}
/**
* 设置是否忽略字段的大小写
*
*
* @param ignoreCase 是否忽略大小写
* @return CopyOptions
*/
@ -144,10 +160,10 @@ public class CopyOptions implements Serializable{
this.ignoreCase = ignoreCase;
return this;
}
/**
* 设置忽略字段的大小写
*
*
* @return CopyOptions
* @since 4.5.7
*/
@ -157,7 +173,7 @@ public class CopyOptions implements Serializable{
/**
* 设置拷贝属性的字段映射用于不同的属性之前拷贝做对应表用
*
*
* @param fieldMapping 拷贝属性的字段映射用于不同的属性之前拷贝做对应表用
* @return CopyOptions
*/
@ -165,13 +181,36 @@ public class CopyOptions implements Serializable{
this.fieldMapping = fieldMapping;
return this;
}
/**
* 是否支持transient关键字修饰和@Transient注解如果支持被修饰的字段或方法对应的字段将被忽略
*
* @return 是否支持
* @since 5.4.2
*/
public boolean isTransientSupport() {
return this.transientSupport;
}
/**
* 设置是否支持transient关键字修饰和@Transient注解如果支持被修饰的字段或方法对应的字段将被忽略
*
* @param transientSupport 是否支持
* @return this
* @since 5.4.2
*/
public CopyOptions setTransientSupport(boolean transientSupport) {
this.transientSupport = transientSupport;
return this;
}
/**
* 获取反转之后的映射
*
* @return 反转映射
* @since 4.1.10
*/
protected Map<String, String> getReversedMapping() {
return (null != this.fieldMapping) ? MapUtil.reverse(this.fieldMapping) : null;
return (null != this.fieldMapping) ? MapUtil.reverse(this.fieldMapping) : null;
}
}

View File

@ -3,11 +3,8 @@ package cn.hutool.core.bean.copier.provider;
import cn.hutool.core.bean.BeanDesc.PropDesc;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.ValueProvider;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.util.StrUtil;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Map;
@ -46,29 +43,32 @@ public class BeanValueProvider implements ValueProvider<String> {
Object result = null;
if (null != sourcePd) {
final Method getter = sourcePd.getGetter();
if (null != getter) {
try {
result = getter.invoke(source);
} catch (Exception e) {
if (false == ignoreError) {
throw new UtilException(e, "Inject [{}] error!", key);
}
}
// 尝试将结果转换为目标类型如果转换失败返回原类型
final Object convertValue = Convert.convertWithCheck(valueType,result, null, ignoreError);
if(null != convertValue){
result = convertValue;
}
}
result = sourcePd.getValueWithConvert(this.source, valueType, this.ignoreError);
}
return result;
}
@Override
public boolean containsKey(String key) {
return sourcePdMap.containsKey(key) || sourcePdMap.containsKey(StrUtil.upperFirstAndAddPre(key, "is"));
PropDesc sourcePd = getPropDesc(key);
// 字段描述不存在或忽略读的情况下表示不存在
return null != sourcePd && false == sourcePd.isIgnoreGet();
}
/**
* 获得属性描述
*
* @param key 字段名
* @return 属性描述
*/
private PropDesc getPropDesc(String key){
PropDesc sourcePd = sourcePdMap.get(key);
if(null == sourcePd) {
//boolean类型字段字段名支持两种方式
sourcePd = sourcePdMap.get(StrUtil.upperFirstAndAddPre(key, "is"));
}
return sourcePd;
}
}

View File

@ -9,10 +9,10 @@ import java.lang.reflect.Type;
import java.util.Map;
/**
* Map值提供者
*
* @author looly
* Map值提供者支持驼峰和下划线的key兼容<br>
* 假设目标属性为firstName则Map中为firstName或first_name都可以对应到值
*
* @author looly
*/
public class MapValueProvider implements ValueProvider<String> {
@ -22,7 +22,7 @@ public class MapValueProvider implements ValueProvider<String> {
/**
* 构造
*
* @param map Map
* @param map Map
* @param ignoreCase 是否忽略key的大小写
*/
public MapValueProvider(Map<?, ?> map, boolean ignoreCase) {
@ -31,17 +31,17 @@ public class MapValueProvider implements ValueProvider<String> {
/**
* 构造
*
* @param map Map
* @param ignoreCase 是否忽略key的大小写
*
* @param map Map
* @param ignoreCase 是否忽略key的大小写
* @param ignoreError 是否忽略错误
* @since 5.3.2
*/
public MapValueProvider(Map<?, ?> map, boolean ignoreCase, boolean ignoreError) {
if(false == ignoreCase || map instanceof CaseInsensitiveMap) {
if (false == ignoreCase || map instanceof CaseInsensitiveMap) {
//不忽略大小写或者提供的Map本身为CaseInsensitiveMap则无需转换
this.map = map;
}else {
} else {
//转换为大小写不敏感的Map
this.map = new CaseInsensitiveMap<>(map);
}
@ -51,7 +51,7 @@ public class MapValueProvider implements ValueProvider<String> {
@Override
public Object value(String key, Type valueType) {
Object value = map.get(key);
if(null == value) {
if (null == value) {
//检查下划线模式
value = map.get(StrUtil.toUnderlineCase(key));
}
@ -61,9 +61,9 @@ public class MapValueProvider implements ValueProvider<String> {
@Override
public boolean containsKey(String key) {
if(map.containsKey(key)) {
if (map.containsKey(key)) {
return true;
}else {
} else {
//检查下划线模式
return map.containsKey(StrUtil.toUnderlineCase(key));
}

View File

@ -32,9 +32,9 @@ public class JSONConfig implements Serializable {
*/
private boolean ignoreNullValue = true;
/**
* 是否忽略transient关键字修饰的字段
* 是否支持transient关键字修饰和@Transient注解如果支持被修饰的字段或方法对应的字段将被忽略
*/
private boolean ignoreTransient = true;
private boolean transientSupport = true;
/**
* 创建默认的配置项
@ -150,9 +150,11 @@ public class JSONConfig implements Serializable {
*
* @return 是否忽略transient关键字修饰的字段
* @since 5.3.11
* @deprecated 此方法名称有二义性请使用{@link #isTransientSupport()}
*/
@Deprecated
public boolean isIgnoreTransient() {
return this.ignoreTransient;
return isTransientSupport();
}
/**
@ -161,9 +163,32 @@ public class JSONConfig implements Serializable {
* @param ignoreTransient 是否忽略transient关键字修饰的字段
* @return this
* @since 5.3.11
* @deprecated 此方法名称有二义性请使用{@link #setTransientSupport(boolean)}
*/
@Deprecated
public JSONConfig setIgnoreTransient(boolean ignoreTransient) {
this.ignoreTransient = ignoreTransient;
return setTransientSupport(ignoreTransient);
}
/**
* 是否支持transient关键字修饰和@Transient注解如果支持被修饰的字段或方法对应的字段将被忽略
*
* @return 是否支持
* @since 5.4.2
*/
public boolean isTransientSupport() {
return this.transientSupport;
}
/**
* 设置是否支持transient关键字修饰和@Transient注解如果支持被修饰的字段或方法对应的字段将被忽略
*
* @param transientSupport 是否支持
* @return this
* @since 5.4.2
*/
public JSONConfig setTransientSupport(boolean transientSupport) {
this.transientSupport = transientSupport;
return this;
}
}

View File

@ -625,7 +625,7 @@ public class JSONObject implements JSON, JSONGetter<String>, Map<String, Object>
Method getter;
Object value;
for (PropDesc prop : props) {
if(this.config.isIgnoreTransient() && prop.isTransient()){
if(this.config.isTransientSupport() && prop.isTransient()){
// 忽略Transient字段和方法
continue;
}