From 0ed9c13f7a58794ca7e88a46eee9a0c4aee47f4d Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 24 Mar 2022 23:26:07 +0800 Subject: [PATCH] fix json --- CHANGELOG.md | 2 + .../cn/hutool/core/convert/Converter.java | 23 +++++++++- .../java/cn/hutool/json/InternalJSONUtil.java | 16 +++++++ .../java/cn/hutool/json/JSONConverter.java | 12 ++++++ .../main/java/cn/hutool/json/JSONObject.java | 9 +--- .../main/java/cn/hutool/json/JSONSupport.java | 4 +- .../java/cn/hutool/json/JSONObjectTest.java | 3 +- .../java/cn/hutool/json/TransientTest.java | 43 ++++++++++++++++++- 8 files changed, 99 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 671643795..2912f05c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ * 【cron 】 【可能兼容问题】SimpleValueParser改名为AbsValueParser,改为abstract * 【poi 】 【可能兼容问题】ExcelUtil.getBigWriter返回值改为BigExcelWriter * 【core 】 【可能兼容问题】Opt.ofEmptyAble参数由List改为Collection子类(pr#580@Gitee) +* 【json 】 【可能兼容问题】JSON转Bean时,使用JSON本身的相关设置,而非默认(issue#2212@Github) ### 🐣新特性 * 【http 】 HttpRequest.form采用TableMap方式(issue#I4W427@Gitee) @@ -57,6 +58,7 @@ * 【http 】 修复标签误删问题(issue#I4Z7BV@Gitee) * 【core 】 修复Win下文件名带*问题(pr#584@Gitee) * 【core 】 FileUtil.getMimeType增加rar、7z支持(issue#I4ZBN0@Gitee) +* 【json 】 JSON修复transient设置无效问题(issue#2212@Github) ------------------------------------------------------------------------------------------------------------- # 5.7.22 (2022-03-01) diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/Converter.java b/hutool-core/src/main/java/cn/hutool/core/convert/Converter.java index ed151cb77..6b1319f0e 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/Converter.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/Converter.java @@ -19,4 +19,25 @@ public interface Converter { */ T convert(Object value, T defaultValue) throws IllegalArgumentException; -} \ No newline at end of file + /** + * 转换值为指定类型,可选是否不抛异常转换
+ * 当转换失败时返回默认值 + * + * @param value 值 + * @param defaultValue 默认值 + * @param quietly 是否静默转换,true不抛异常 + * @return 转换后的值 + * @since 5.8.0 + * @see #convert(Object, Object) + */ + default T convertWithCheck(Object value, T defaultValue, boolean quietly) { + try { + return convert(value, defaultValue); + } catch (Exception e) { + if(quietly){ + return defaultValue; + } + throw e; + } + } +} diff --git a/hutool-json/src/main/java/cn/hutool/json/InternalJSONUtil.java b/hutool-json/src/main/java/cn/hutool/json/InternalJSONUtil.java index 960b6d9ef..af7e617e3 100644 --- a/hutool-json/src/main/java/cn/hutool/json/InternalJSONUtil.java +++ b/hutool-json/src/main/java/cn/hutool/json/InternalJSONUtil.java @@ -1,5 +1,6 @@ package cn.hutool.json; +import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.convert.Convert; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.CharUtil; @@ -191,4 +192,19 @@ public final class InternalJSONUtil { return false; } + + /** + * 将{@link JSONConfig}参数转换为Bean拷贝所用的{@link CopyOptions} + * + * @param config {@link JSONConfig} + * @return {@link CopyOptions} + * @since 5.8.0 + */ + static CopyOptions toCopyOptions(JSONConfig config) { + return CopyOptions.create() + .setIgnoreCase(config.isIgnoreCase()) + .setIgnoreError(config.isIgnoreError()) + .setIgnoreNullValue(config.isIgnoreNullValue()) + .setTransientSupport(config.isTransientSupport()); + } } diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONConverter.java b/hutool-json/src/main/java/cn/hutool/json/JSONConverter.java index 7f5ef5ced..674ee98d1 100644 --- a/hutool-json/src/main/java/cn/hutool/json/JSONConverter.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONConverter.java @@ -1,10 +1,12 @@ package cn.hutool.json; +import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.ConvertException; import cn.hutool.core.convert.Converter; import cn.hutool.core.convert.ConverterRegistry; import cn.hutool.core.convert.impl.ArrayConverter; +import cn.hutool.core.convert.impl.BeanConverter; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ReflectUtil; import cn.hutool.core.util.StrUtil; @@ -112,6 +114,16 @@ public class JSONConverter implements Converter { //noinspection unchecked return (T) deserializer.deserialize((JSON) value); } + + // issue#2212@Github + // 在JSONObject转Bean时,读取JSONObject本身的配置文件 + if(value instanceof JSONGetter + && targetType instanceof Class && BeanUtil.hasSetter((Class) targetType)){ + final JSONConfig config = ((JSONGetter) value).getConfig(); + final Converter converter = new BeanConverter<>(targetType, + InternalJSONUtil.toCopyOptions(config).setIgnoreError(ignoreError)); + return converter.convertWithCheck(value, null, ignoreError); + } } final T targetValue = Convert.convertWithCheck(targetType, value, null, ignoreError); diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONObject.java b/hutool-json/src/main/java/cn/hutool/json/JSONObject.java index 8ac79a341..4dbbc1b21 100644 --- a/hutool-json/src/main/java/cn/hutool/json/JSONObject.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONObject.java @@ -2,8 +2,6 @@ package cn.hutool.json; import cn.hutool.core.bean.BeanPath; import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.bean.copier.BeanCopier; -import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.lang.Filter; @@ -537,12 +535,7 @@ public class JSONObject extends MapWrapper implements JSON, JSON * @param bean Bean对象 */ private void populateMap(Object bean) { - BeanCopier.create(bean, this, - CopyOptions.create() - .setIgnoreCase(config.isIgnoreCase()) - .setIgnoreError(true) - .setIgnoreNullValue(config.isIgnoreNullValue()) - ).copy(); + BeanUtil.beanToMap(bean, this, InternalJSONUtil.toCopyOptions(config)); } /** diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONSupport.java b/hutool-json/src/main/java/cn/hutool/json/JSONSupport.java index d971e49b4..89a1639ce 100644 --- a/hutool-json/src/main/java/cn/hutool/json/JSONSupport.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONSupport.java @@ -20,9 +20,9 @@ public class JSONSupport implements JSONString, JSONBeanParser { } /** - * JSON String转Bean + * JSON转Bean * - * @param json JSON String + * @param json JSON */ @Override public void parse(JSON json) { diff --git a/hutool-json/src/test/java/cn/hutool/json/JSONObjectTest.java b/hutool-json/src/test/java/cn/hutool/json/JSONObjectTest.java index afa1616f0..249d458a5 100644 --- a/hutool-json/src/test/java/cn/hutool/json/JSONObjectTest.java +++ b/hutool-json/src/test/java/cn/hutool/json/JSONObjectTest.java @@ -188,10 +188,11 @@ public class JSONObjectTest { JSONObject json = JSONUtil.createObj()// .set("strValue", "null")// .set("intValue", 123)// + // 子对象对应"null"字符串,如果忽略错误,跳过,否则抛出转换异常 .set("beanValue", "null")// .set("list", JSONUtil.createArray().set("a").set("b")); - TestBean bean = json.toBean(TestBean.class); + TestBean bean = json.toBean(TestBean.class, true); // 当JSON中为字符串"null"时应被当作字符串处理 Assert.assertEquals("null", bean.getStrValue()); // 当JSON中为字符串"null"时Bean中的字段类型不匹配应在ignoreError模式下忽略注入 diff --git a/hutool-json/src/test/java/cn/hutool/json/TransientTest.java b/hutool-json/src/test/java/cn/hutool/json/TransientTest.java index 268444887..d179d5c71 100644 --- a/hutool-json/src/test/java/cn/hutool/json/TransientTest.java +++ b/hutool-json/src/test/java/cn/hutool/json/TransientTest.java @@ -12,14 +12,55 @@ public class TransientTest { private String bizNo; } + @Test + public void beanWithoutTransientTest(){ + Bill detailBill = new Bill(); + detailBill.setId("3243"); + detailBill.setBizNo("bizNo"); + + //noinspection MismatchedQueryAndUpdateOfCollection + final JSONObject jsonObject = new JSONObject(detailBill, + JSONConfig.create().setTransientSupport(false)); + Assert.assertEquals("{\"bizNo\":\"bizNo\",\"id\":\"3243\"}", jsonObject.toString()); + } + @Test public void beanWithTransientTest(){ Bill detailBill = new Bill(); detailBill.setId("3243"); detailBill.setBizNo("bizNo"); + //noinspection MismatchedQueryAndUpdateOfCollection + final JSONObject jsonObject = new JSONObject(detailBill, + JSONConfig.create().setTransientSupport(true)); + Assert.assertEquals("{\"bizNo\":\"bizNo\"}", jsonObject.toString()); + } + + @Test + public void beanWithoutTransientToBeanTest(){ + Bill detailBill = new Bill(); + detailBill.setId("3243"); + detailBill.setBizNo("bizNo"); + final JSONObject jsonObject = new JSONObject(detailBill, JSONConfig.create().setTransientSupport(false)); - Assert.assertEquals("{\"bizNo\":\"bizNo\"}", jsonObject.toString()); + + final Bill bill = jsonObject.toBean(Bill.class); + Assert.assertEquals("3243", bill.getId()); + Assert.assertEquals("bizNo", bill.getBizNo()); + } + + @Test + public void beanWithTransientToBeanTest(){ + Bill detailBill = new Bill(); + detailBill.setId("3243"); + detailBill.setBizNo("bizNo"); + + final JSONObject jsonObject = new JSONObject(detailBill, + JSONConfig.create().setTransientSupport(true)); + + final Bill bill = jsonObject.toBean(Bill.class); + Assert.assertNull(bill.getId()); + Assert.assertEquals("bizNo", bill.getBizNo()); } }