From 2d1fc30c271079fd9a9a84ceacd54fd2e5f43ec2 Mon Sep 17 00:00:00 2001 From: Looly Date: Sat, 30 Oct 2021 02:23:28 +0800 Subject: [PATCH] fix code --- CHANGELOG.md | 3 +- .../main/java/cn/hutool/core/lang/Pair.java | 8 +- .../core/lang/mutable/MutableDouble.java | 8 +- .../hutool/core/lang/mutable/MutablePair.java | 57 +++++++++++++ .../java/cn/hutool/core/util/ArrayUtil.java | 5 +- .../java/cn/hutool/core/util/ObjectUtil.java | 6 +- .../main/java/cn/hutool/json/JSONArray.java | 22 ++--- .../main/java/cn/hutool/json/JSONObject.java | 15 ++-- .../java/cn/hutool/json/JSONObjectTest.java | 80 ++++++++++++++----- 9 files changed, 150 insertions(+), 54 deletions(-) create mode 100644 hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutablePair.java diff --git a/CHANGELOG.md b/CHANGELOG.md index b705ebf86..a21c83482 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ------------------------------------------------------------------------------------------------------------- -# 5.7.16 (2021-10-29) +# 5.7.16 (2021-10-30) ### 🐣新特性 * 【core 】 增加DateTime.toLocalDateTime @@ -16,6 +16,7 @@ * 【core 】 TemporalUtil增加toChronoUnit、toTimeUnit方法(issue#I4FGDH@Gitee) * 【core 】 StopWatch增加prettyPrint重载(issue#1910@Github) * 【core 】 修改RegexPool中Ipv4正则 +* 【json 】 Filter改为MutablePair,以便编辑键值对(issue#1921@Github) ### 🐞Bug修复 * 【core 】 修复UrlBuilder.addPath歧义问题(issue#1912@Github) diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/Pair.java b/hutool-core/src/main/java/cn/hutool/core/lang/Pair.java index b6cfa3ca8..a7cb9cd69 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/Pair.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/Pair.java @@ -16,17 +16,17 @@ import java.util.Objects; public class Pair extends CloneSupport> implements Serializable { private static final long serialVersionUID = 1L; - private final K key; - private final V value; + protected K key; + protected V value; /** - * 构建{@link Pair}对象 + * 构建{@code Pair}对象 * * @param 键类型 * @param 值类型 * @param key 键 * @param value 值 - * @return {@link Pair} + * @return {@code Pair} * @since 5.4.3 */ public static Pair of(K key, V value) { diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableDouble.java b/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableDouble.java index 31a72d8bd..17702fbe7 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableDouble.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableDouble.java @@ -3,7 +3,7 @@ package cn.hutool.core.lang.mutable; import cn.hutool.core.util.NumberUtil; /** - * 可变 double 类型 + * 可变 {@code double} 类型 * * @see Double * @since 3.0.1 @@ -150,12 +150,12 @@ public class MutableDouble extends Number implements Comparable, * 相等需同时满足如下条件: *
    *
  1. 非空
  2. - *
  3. 类型为 {@link MutableDouble}
  4. + *
  5. 类型为 {@code MutableDouble}
  6. *
  7. 值相等
  8. *
* * @param obj 比对的对象 - * @return 相同返回true,否则 false + * @return 相同返回true,否则 {@code false} */ @Override public boolean equals(final Object obj) { @@ -175,7 +175,7 @@ public class MutableDouble extends Number implements Comparable, /** * 比较 * - * @param other 其它 {@link MutableDouble} 对象 + * @param other 其它 {@code MutableDouble} 对象 * @return x==y返回0,x<y返回-1,x>y返回1 */ @Override diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutablePair.java b/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutablePair.java new file mode 100644 index 000000000..7e5538515 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutablePair.java @@ -0,0 +1,57 @@ +package cn.hutool.core.lang.mutable; + +import cn.hutool.core.lang.Pair; + +/** + * 可变{@link Pair}实现,可以修改键和值 + * + * @param 键类型 + * @param 值类型 + * @since 5.7.16 + */ +public class MutablePair extends Pair implements Mutable>{ + private static final long serialVersionUID = 1L; + + /** + * 构造 + * + * @param key 键 + * @param value 值 + */ + public MutablePair(K key, V value) { + super(key, value); + } + + /** + * 设置键 + * + * @param key 新键 + * @return this + */ + public MutablePair setKey(K key) { + this.key = key; + return this; + } + + /** + * 设置值 + * + * @param value 新值 + * @return this + */ + public MutablePair setValue(V value) { + this.value = value; + return this; + } + + @Override + public Pair get() { + return this; + } + + @Override + public void set(Pair pair) { + this.key = pair.getKey(); + this.value = pair.getValue(); + } +} diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java index 5912fd56b..adc11b2f8 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java @@ -22,7 +22,6 @@ import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Random; import java.util.Set; import java.util.function.Function; @@ -118,7 +117,7 @@ public class ArrayUtil extends PrimitiveArrayUtil { public static boolean hasNull(T... array) { if (isNotEmpty(array)) { for (T element : array) { - if (null == element) { + if (ObjectUtil.isNull(element)) { return true; } } @@ -150,7 +149,7 @@ public class ArrayUtil extends PrimitiveArrayUtil { */ @SuppressWarnings("unchecked") public static T firstNonNull(T... array) { - return firstMatch(Objects::nonNull, array); + return firstMatch(ObjectUtil::isNotNull, array); } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ObjectUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ObjectUtil.java index 2c84590ac..eeab6d5fc 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/ObjectUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/ObjectUtil.java @@ -292,7 +292,7 @@ public class ObjectUtil { * @since 3.0.7 */ public static T defaultIfNull(final T object, final T defaultValue) { - return (null != object) ? object : defaultValue; + return isNull(object) ? defaultValue : object; } @@ -300,14 +300,14 @@ public class ObjectUtil { * 如果给定对象为{@code null} 返回默认值, 如果不为null 返回自定义handle处理后的返回值 * * @param source Object 类型对象 - * @param handle 自定义的处理方法 + * @param handle 非空时自定义的处理方法 * @param defaultValue 默认为空的返回值 * @param 被检查对象为{@code null}返回默认值,否则返回自定义handle处理后的返回值 * @return 处理后的返回值 * @since 5.4.6 */ public static T defaultIfNull(Object source, Supplier handle, final T defaultValue) { - if (Objects.nonNull(source)) { + if (isNotNull(source)) { return handle.get(); } return defaultValue; diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONArray.java b/hutool-json/src/main/java/cn/hutool/json/JSONArray.java index 3cdea5a83..df5f34f13 100644 --- a/hutool-json/src/main/java/cn/hutool/json/JSONArray.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONArray.java @@ -4,7 +4,7 @@ import cn.hutool.core.bean.BeanPath; import cn.hutool.core.collection.ArrayIter; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Filter; -import cn.hutool.core.lang.Pair; +import cn.hutool.core.lang.mutable.MutablePair; import cn.hutool.core.text.StrJoiner; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ObjectUtil; @@ -446,13 +446,13 @@ public class JSONArray implements JSON, JSONGetter, List, Rando /** * 加入或者替换JSONArray中指定Index的值,如果index大于JSONArray的长度,将在指定index设置值,之前的位置填充JSONNull.Null * - * @param index 位置 + * @param index 位置 * @param element 值对象. 可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL. * @return 替换的值,即之前的值 */ @Override public Object set(int index, Object element) { - if(index >= size()){ + if (index >= size()) { add(index, element); } return this.rawList.set(index, JSONUtil.wrap(element, this.config)); @@ -537,11 +537,11 @@ public class JSONArray implements JSON, JSONGetter, List, Rando * 支持过滤器,即选择哪些字段或值不写出 * * @param indentFactor 每层缩进空格数 - * @param filter 键值对过滤器 + * @param filter 过滤器,可以修改值,key(index)无法修改 * @return JSON字符串 * @since 5.7.15 */ - public String toJSONString(int indentFactor, Filter> filter){ + public String toJSONString(int indentFactor, Filter> filter) { final StringWriter sw = new StringWriter(); synchronized (sw.getBuffer()) { return this.write(sw, indentFactor, 0, filter).toString(); @@ -560,18 +560,19 @@ public class JSONArray implements JSON, JSONGetter, List, Rando * @param writer writer * @param indentFactor 缩进因子,定义每一级别增加的缩进量 * @param indent 本级别缩进量 - * @param filter 过滤器 + * @param filter 过滤器,可以修改值,key(index)无法修改 * @return Writer * @throws JSONException JSON相关异常 * @since 5.7.15 */ - public Writer write(Writer writer, int indentFactor, int indent, Filter> filter) throws JSONException { + public Writer write(Writer writer, int indentFactor, int indent, Filter> filter) throws JSONException { final JSONWriter jsonWriter = JSONWriter.of(writer, indentFactor, indent, config) .beginArray(); - CollUtil.forEach(this, (value, index)->{ - if (null == filter || filter.accept(new Pair<>(index, value))) { - jsonWriter.writeValue(value); + CollUtil.forEach(this, (value, index) -> { + final MutablePair pair = new MutablePair<>(index, value); + if (null == filter || filter.accept(pair)) { + jsonWriter.writeValue(pair.getValue()); } }); jsonWriter.end(); @@ -580,6 +581,7 @@ public class JSONArray implements JSON, JSONGetter, List, Rando } // ------------------------------------------------------------------------------------------------- Private method start + /** * 初始化 * 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 7358cedec..ca7c08613 100644 --- a/hutool-json/src/main/java/cn/hutool/json/JSONObject.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONObject.java @@ -7,7 +7,7 @@ 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; -import cn.hutool.core.lang.Pair; +import cn.hutool.core.lang.mutable.MutablePair; import cn.hutool.core.map.CaseInsensitiveLinkedMap; import cn.hutool.core.map.CaseInsensitiveMap; import cn.hutool.core.map.MapUtil; @@ -560,11 +560,11 @@ public class JSONObject implements JSON, JSONGetter, Map * 支持过滤器,即选择哪些字段或值不写出 * * @param indentFactor 每层缩进空格数 - * @param filter 键值对过滤器 + * @param filter 过滤器,同时可以修改编辑键和值 * @return JSON字符串 * @since 5.7.15 */ - public String toJSONString(int indentFactor, Filter> filter){ + public String toJSONString(int indentFactor, Filter> filter) { final StringWriter sw = new StringWriter(); synchronized (sw.getBuffer()) { return this.write(sw, indentFactor, 0, filter).toString(); @@ -583,17 +583,18 @@ public class JSONObject implements JSON, JSONGetter, Map * @param writer writer * @param indentFactor 缩进因子,定义每一级别增加的缩进量 * @param indent 本级别缩进量 - * @param filter 过滤器 + * @param filter 过滤器,同时可以修改编辑键和值 * @return Writer * @throws JSONException JSON相关异常 * @since 5.7.15 */ - public Writer write(Writer writer, int indentFactor, int indent, Filter> filter) throws JSONException { + public Writer write(Writer writer, int indentFactor, int indent, Filter> filter) throws JSONException { final JSONWriter jsonWriter = JSONWriter.of(writer, indentFactor, indent, config) .beginObj(); this.forEach((key, value) -> { - if (null == filter || filter.accept(new Pair<>(key, value))) { - jsonWriter.writeField(key, value); + final MutablePair pair = new MutablePair<>(key, value); + if (null == filter || filter.accept(pair)) { + jsonWriter.writeField(pair.getKey(), pair.getValue()); } }); jsonWriter.end(); 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 f2983b859..f3ae62388 100644 --- a/hutool-json/src/test/java/cn/hutool/json/JSONObjectTest.java +++ b/hutool-json/src/test/java/cn/hutool/json/JSONObjectTest.java @@ -10,6 +10,7 @@ import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.resource.ResourceUtil; import cn.hutool.core.lang.Console; import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.json.test.bean.JSONBean; import cn.hutool.json.test.bean.ResultDto; @@ -67,7 +68,7 @@ public class JSONObjectTest { @Test public void toStringTest3() { JSONObject json = Objects.requireNonNull(JSONUtil.createObj()// - .set("dateTime", DateUtil.parse("2019-05-02 22:12:01")))// + .set("dateTime", DateUtil.parse("2019-05-02 22:12:01")))// .setDateFormat(DatePattern.NORM_DATE_PATTERN); Assert.assertEquals("{\"dateTime\":\"2019-05-02\"}", json.toString()); } @@ -86,14 +87,14 @@ public class JSONObjectTest { @Test public void putAllTest() { JSONObject json1 = JSONUtil.createObj() - .set("a", "value1") - .set("b", "value2") - .set("c", "value3") - .set("d", true); + .set("a", "value1") + .set("b", "value2") + .set("c", "value3") + .set("d", true); JSONObject json2 = JSONUtil.createObj() - .set("a", "value21") - .set("b", "value22"); + .set("a", "value21") + .set("b", "value22"); // putAll操作会覆盖相同key的值,因此a,b两个key的值改变,c的值不变 json1.putAll(json2); @@ -399,7 +400,7 @@ public class JSONObjectTest { } @Test - public void aliasTest(){ + public void aliasTest() { final BeanWithAlias beanWithAlias = new BeanWithAlias(); beanWithAlias.setValue1("张三"); beanWithAlias.setValue2(35); @@ -417,7 +418,7 @@ public class JSONObjectTest { } @Test - public void setDateFormatTest(){ + public void setDateFormatTest() { JSONConfig jsonConfig = JSONConfig.create(); jsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss"); jsonConfig.setOrder(true); @@ -430,7 +431,7 @@ public class JSONObjectTest { } @Test - public void setDateFormatTest2(){ + public void setDateFormatTest2() { JSONConfig jsonConfig = JSONConfig.create(); jsonConfig.setDateFormat("yyyy#MM#dd"); jsonConfig.setOrder(true); @@ -451,7 +452,7 @@ public class JSONObjectTest { } @Test - public void setCustomDateFormatTest(){ + public void setCustomDateFormatTest() { JSONConfig jsonConfig = JSONConfig.create(); jsonConfig.setDateFormat("#sss"); jsonConfig.setOrder(true); @@ -472,7 +473,7 @@ public class JSONObjectTest { } @Test - public void getTimestampTest(){ + public void getTimestampTest() { String timeStr = "1970-01-01 00:00:00"; final JSONObject jsonObject = JSONUtil.createObj().set("time", timeStr); final Timestamp time = jsonObject.get("time", Timestamp.class); @@ -518,7 +519,7 @@ public class JSONObjectTest { } @Test - public void parseBeanSameNameTest(){ + public void parseBeanSameNameTest() { final SameNameBean sameNameBean = new SameNameBean(); final JSONObject parse = JSONUtil.parseObj(sameNameBean); Assert.assertEquals("123", parse.getStr("username")); @@ -537,9 +538,11 @@ public class JSONObjectTest { public static class SameNameBean { private final String username = "123"; private final String userName = "abc"; + public String getUsername() { return username; } + @PropIgnore private final String fieldToIgnore = "sfdsdads"; @@ -547,13 +550,13 @@ public class JSONObjectTest { return userName; } - public String getFieldToIgnore(){ + public String getFieldToIgnore() { return this.fieldToIgnore; } } @Test - public void setEntryTest(){ + public void setEntryTest() { final HashMap of = MapUtil.of("test", "testValue"); final Set> entries = of.entrySet(); final Map.Entry next = entries.iterator().next(); @@ -563,13 +566,13 @@ public class JSONObjectTest { } @Test(expected = JSONException.class) - public void createJSONObjectTest(){ + public void createJSONObjectTest() { // 集合类不支持转为JSONObject new JSONObject(new JSONArray(), JSONConfig.create()); } @Test - public void floatTest(){ + public void floatTest() { Map map = new HashMap<>(); map.put("c", 2.0F); @@ -578,7 +581,7 @@ public class JSONObjectTest { } @Test - public void accumulateTest(){ + public void accumulateTest() { final JSONObject jsonObject = JSONUtil.createObj().accumulate("key1", "value1"); Assert.assertEquals("{\"key1\":\"value1\"}", jsonObject.toString()); @@ -598,7 +601,7 @@ public class JSONObjectTest { @Test - public void bigDecimalTest(){ + public void bigDecimalTest() { String jsonStr = "{\"orderId\":\"1704747698891333662002277\"}"; BigDecimalBean bigDecimalBean = JSONUtil.toBean(jsonStr, BigDecimalBean.class); Assert.assertEquals("{\"orderId\":1704747698891333662002277}", JSONUtil.toJsonStr(bigDecimalBean)); @@ -606,12 +609,12 @@ public class JSONObjectTest { @Data static - class BigDecimalBean{ + class BigDecimalBean { private BigDecimal orderId; } @Test - public void filterIncludeTest(){ + public void filterIncludeTest() { JSONObject json1 = JSONUtil.createObj(JSONConfig.create().setOrder(true)) .set("a", "value1") .set("b", "value2") @@ -623,7 +626,7 @@ public class JSONObjectTest { } @Test - public void filterExcludeTest(){ + public void filterExcludeTest() { JSONObject json1 = JSONUtil.createObj(JSONConfig.create().setOrder(true)) .set("a", "value1") .set("b", "value2") @@ -633,4 +636,37 @@ public class JSONObjectTest { final String s = json1.toJSONString(0, (pair) -> false == pair.getKey().equals("b")); Assert.assertEquals("{\"a\":\"value1\",\"c\":\"value3\",\"d\":true}", s); } + + @Test + public void editTest() { + JSONObject json1 = JSONUtil.createObj(JSONConfig.create().setOrder(true)) + .set("a", "value1") + .set("b", "value2") + .set("c", "value3") + .set("d", true); + + final String s = json1.toJSONString(0, (pair) -> { + if ("b".equals(pair.getKey())) { + // 修改值为新值 + pair.setValue(pair.getValue() + "_edit"); + return true; + } + // 除了"b",其他都去掉 + return false; + }); + Assert.assertEquals("{\"b\":\"value2_edit\"}", s); + } + + @Test + public void nullToEmptyTest() { + JSONObject json1 = JSONUtil.createObj(JSONConfig.create().setOrder(true).setIgnoreNullValue(false)) + .set("a", null) + .set("b", "value2"); + + final String s = json1.toJSONString(0, (pair) -> { + pair.setValue(ObjectUtil.defaultIfNull(pair.getValue(), StrUtil.EMPTY)); + return true; + }); + Assert.assertEquals("{\"a\":\"\",\"b\":\"value2\"}", s); + } }