diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ObjUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ObjUtil.java index 10eee71d1..79e359785 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/ObjUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/ObjUtil.java @@ -186,15 +186,13 @@ public class ObjUtil { * *
 	 * 1. == null
-	 * 2. equals(null)
 	 * 
* * @param obj 对象 * @return 是否为null */ public static boolean isNull(final Object obj) { - //noinspection ConstantConditions - return null == obj || obj.equals(null); + return null == obj; } /** 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 7c326e38e..f1000813a 100755 --- a/hutool-json/src/main/java/cn/hutool/json/InternalJSONUtil.java +++ b/hutool-json/src/main/java/cn/hutool/json/InternalJSONUtil.java @@ -59,8 +59,8 @@ public final class InternalJSONUtil { * @throws JSONException If the value is or contains an invalid number. */ static String valueToString(final Object value) throws JSONException { - if (value == null || value instanceof JSONNull) { - return JSONNull.NULL.toString(); + if (value == null) { + return StrUtil.NULL; } if (value instanceof JSONString) { try { @@ -94,7 +94,7 @@ public final class InternalJSONUtil { public static Object stringToValue(final String string) { // null处理 if (StrUtil.isEmpty(string) || StrUtil.NULL.equalsIgnoreCase(string)) { - return JSONNull.NULL; + return null; } // boolean处理 diff --git a/hutool-json/src/main/java/cn/hutool/json/JSON.java b/hutool-json/src/main/java/cn/hutool/json/JSON.java index 4d0cf063e..e06aaa72c 100755 --- a/hutool-json/src/main/java/cn/hutool/json/JSON.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSON.java @@ -36,7 +36,9 @@ public interface JSON extends Cloneable, Serializable { * @see BeanPath#get(Object) * @since 4.0.6 */ - Object getByPath(String expression); + default Object getByPath(String expression){ + return BeanPath.of(expression).get(this); + } /** * 设置表达式指定位置(或filed对应)的值
@@ -59,7 +61,9 @@ public interface JSON extends Cloneable, Serializable { * @param expression 表达式 * @param value 值 */ - void putByPath(String expression, Object value); + default void putByPath(String expression, Object value){ + BeanPath.of(expression).set(this, value); + } /** * 通过表达式获取JSON中嵌套的对象
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 30c01f3e4..2fe50ad3f 100755 --- a/hutool-json/src/main/java/cn/hutool/json/JSONArray.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONArray.java @@ -1,13 +1,12 @@ package cn.hutool.json; -import cn.hutool.core.bean.BeanPath; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.impl.ArrayConverter; import cn.hutool.core.lang.func.Filter; import cn.hutool.core.lang.mutable.Mutable; -import cn.hutool.core.lang.mutable.MutableObj; import cn.hutool.core.lang.mutable.MutableEntry; +import cn.hutool.core.lang.mutable.MutableObj; import cn.hutool.core.text.StrJoiner; import cn.hutool.core.util.ObjUtil; import cn.hutool.json.serialize.JSONWriter; @@ -192,19 +191,9 @@ public class JSONArray implements JSON, JSONGetter, List, Rando return (index < 0 || index >= this.size()) ? defaultValue : this.rawList.get(index); } - @Override - public Object getByPath(final String expression) { - return BeanPath.of(expression).get(this); - } - @Override public T getByPath(final String expression, final Class resultType) { - return JSONConverter.jsonConvert(resultType, getByPath(expression), true); - } - - @Override - public void putByPath(final String expression, final Object value) { - BeanPath.of(expression).set(this, value); + return JSONConverter.jsonConvert(resultType, getByPath(expression), this.config.isIgnoreError()); } /** @@ -376,6 +365,9 @@ public class JSONArray implements JSON, JSONGetter, List, Rando } final ArrayList list = new ArrayList<>(c.size()); for (final Object object : c) { + if(null == object && config.isIgnoreNullValue()){ + continue; + } list.add(JSONUtil.wrap(object, this.config)); } return rawList.addAll(index, list); @@ -428,25 +420,36 @@ public class JSONArray implements JSON, JSONGetter, List, Rando } } + // 越界则追加到指定位置 if (index >= size()) { add(index, element); + return null; + } + if(null == element && config.isIgnoreNullValue()){ + return null; } return this.rawList.set(index, JSONUtil.wrap(element, this.config)); } @Override - public void add(final int index, final Object element) { - if (index < 0) { - throw new JSONException("JSONArray[{}] not found.", index); + public void add(int index, final Object element) { + if(null == element && config.isIgnoreNullValue()){ + return; } if (index < this.size()) { + if (index < 0) { + index = 0; + } InternalJSONUtil.testValidity(element); this.rawList.add(index, JSONUtil.wrap(element, this.config)); } else { - while (index != this.size()) { - this.add(JSONNull.NULL); + if(false == config.isIgnoreNullValue()){ + while (index != this.size()) { + // 非末尾,则填充null + this.add(null); + } } - this.set(element); + this.add(element); } } @@ -583,6 +586,10 @@ public class JSONArray implements JSON, JSONGetter, List, Rando return false; } } + if(null == obj && config.isIgnoreNullValue()){ + // 忽略空则不添加 + return false; + } return this.rawList.add(obj); } } 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 d2f06827b..990d902bb 100644 --- a/hutool-json/src/main/java/cn/hutool/json/JSONConverter.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONConverter.java @@ -53,7 +53,7 @@ public class JSONConverter implements Converter { */ @SuppressWarnings("unchecked") protected static T jsonConvert(final Type targetType, final Object value, final boolean ignoreError) throws ConvertException { - if (JSONUtil.isNull(value)) { + if (null == value) { return null; } @@ -91,7 +91,7 @@ public class JSONConverter implements Converter { */ @SuppressWarnings("unchecked") protected static T jsonToBean(final Type targetType, final Object value, final boolean ignoreError) throws ConvertException { - if (JSONUtil.isNull(value)) { + if (null == value) { return null; } diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONGetter.java b/hutool-json/src/main/java/cn/hutool/json/JSONGetter.java index 981e2e6fc..5efbdf656 100644 --- a/hutool-json/src/main/java/cn/hutool/json/JSONGetter.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONGetter.java @@ -6,6 +6,7 @@ import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.LocalDateTimeUtil; import cn.hutool.core.lang.getter.OptNullBasicTypeFromObjectGetter; import cn.hutool.core.text.StrUtil; +import cn.hutool.core.util.ObjUtil; import java.time.LocalDateTime; import java.util.Date; @@ -32,10 +33,10 @@ public interface JSONGetter extends OptNullBasicTypeFromObjectGetter { * key对应值是否为{@code null}或无此key * * @param key 键 - * @return true 无此key或值为{@code null}或{@link JSONNull#NULL}返回{@code false},其它返回{@code true} + * @return true 无此key或值为{@code null}返回{@code false},其它返回{@code true} */ default boolean isNull(final K key) { - return JSONUtil.isNull(this.getObj(key)); + return ObjUtil.isNull(this.getObj(key)); } /** @@ -70,7 +71,7 @@ public interface JSONGetter extends OptNullBasicTypeFromObjectGetter { */ default JSONArray getJSONArray(final K key) { final Object object = this.getObj(key); - if (JSONUtil.isNull(object)) { + if (ObjUtil.isNull(object)) { return null; } @@ -89,7 +90,7 @@ public interface JSONGetter extends OptNullBasicTypeFromObjectGetter { */ default JSONObject getJSONObject(final K key) { final Object object = this.getObj(key); - if (JSONUtil.isNull(object)) { + if (ObjUtil.isNull(object)) { return null; } @@ -133,7 +134,7 @@ public interface JSONGetter extends OptNullBasicTypeFromObjectGetter { default Date getDate(final K key, final Date defaultValue) { // 默认转换 final Object obj = getObj(key); - if (JSONUtil.isNull(obj)) { + if (ObjUtil.isNull(obj)) { return defaultValue; } if (obj instanceof Date) { @@ -167,7 +168,7 @@ public interface JSONGetter extends OptNullBasicTypeFromObjectGetter { default LocalDateTime getLocalDateTime(final K key, final LocalDateTime defaultValue) { // 默认转换 final Object obj = getObj(key); - if (JSONUtil.isNull(obj)) { + if (ObjUtil.isNull(obj)) { return defaultValue; } if (obj instanceof LocalDateTime) { @@ -228,7 +229,7 @@ public interface JSONGetter extends OptNullBasicTypeFromObjectGetter { */ default T get(final K key, final Class type, final boolean ignoreError) throws ConvertException { final Object value = this.getObj(key); - if (JSONUtil.isNull(value)) { + if (ObjUtil.isNull(value)) { return null; } return JSONConverter.jsonConvert(type, value, ignoreError); diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONNull.java b/hutool-json/src/main/java/cn/hutool/json/JSONNull.java deleted file mode 100644 index 27a4442fa..000000000 --- a/hutool-json/src/main/java/cn/hutool/json/JSONNull.java +++ /dev/null @@ -1,46 +0,0 @@ -package cn.hutool.json; - -import cn.hutool.core.text.StrUtil; - -import java.io.Serializable; - -/** - * 用于定义{@code null},与Javascript中null相对应
- * Java中的{@code null}值在js中表示为undefined。 - * - * @author Looly - */ -public class JSONNull implements Serializable { - private static final long serialVersionUID = 2633815155870764938L; - - /** - * {@code NULL} 对象用于减少歧义来表示Java 中的{@code null}
- * {@code NULL.equals(null)} 返回 {@code true}.
- * {@code NULL.toString()} 返回 {@code "null"}. - */ - public static final JSONNull NULL = new JSONNull(); - - /** - * A Null object is equal to the null value and to itself. - * 对象与其本身和{@code null}值相等 - * - * @param object An object to test for nullness. - * @return true if the object parameter is the JSONObject.NULL object or null. - */ - @SuppressWarnings("EqualsWhichDoesntCheckParameterClass") - @Override - public boolean equals(final Object object) { - return object == null || (object == this); - } - - /** - * Get the "null" string value. - * 获得“null”字符串 - * - * @return The string "null". - */ - @Override - public String toString() { - return StrUtil.NULL; - } -} 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 7d9388bcf..99be5b560 100755 --- a/hutool-json/src/main/java/cn/hutool/json/JSONObject.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONObject.java @@ -1,6 +1,5 @@ package cn.hutool.json; -import cn.hutool.core.bean.BeanPath; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.func.Filter; import cn.hutool.core.lang.mutable.MutableEntry; @@ -182,19 +181,9 @@ public class JSONObject extends MapWrapper implements JSON, JSON return this.getOrDefault(key, defaultValue); } - @Override - public Object getByPath(final String expression) { - return BeanPath.of(expression).get(this); - } - @Override public T getByPath(final String expression, final Class resultType) { - return JSONConverter.jsonConvert(resultType, getByPath(expression), true); - } - - @Override - public void putByPath(final String expression, final Object value) { - BeanPath.of(expression).set(this, value); + return JSONConverter.jsonConvert(resultType, getByPath(expression), this.config.isIgnoreError()); } /** @@ -219,7 +208,23 @@ public class JSONObject extends MapWrapper implements JSON, JSON * @throws JSONException 值是无穷数字抛出此异常 */ public JSONObject set(final String key, final Object value) throws JSONException { - return set(key, value, null, false); + put(key, value, null, false); + return this; + } + + /** + * 一次性Put 键值对,如果key已经存在抛出异常,如果键值中有null值,忽略 + * + * @param key 键 + * @param value 值对象,可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL. + * @param filter 键值对过滤编辑器,可以通过实现此接口,完成解析前对键值对的过滤和修改操作,{@code null}表示不过滤 + * @return this + * @throws JSONException 值是无穷数字、键重复抛出异常 + * @since 5.8.0 + */ + public JSONObject setOnce(final String key, final Object value, final Filter> filter) throws JSONException { + put(key, value, filter, true); + return this; } /** @@ -238,32 +243,6 @@ public class JSONObject extends MapWrapper implements JSON, JSON return this; } - /** - * 一次性Put 键值对,如果key已经存在抛出异常,如果键值中有null值,忽略 - * - * @param key 键 - * @param value 值对象,可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL. - * @return this. - * @throws JSONException 值是无穷数字、键重复抛出异常 - */ - public JSONObject putOnce(final String key, final Object value) throws JSONException { - return setOnce(key, value, null); - } - - /** - * 一次性Put 键值对,如果key已经存在抛出异常,如果键值中有null值,忽略 - * - * @param key 键 - * @param value 值对象,可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL. - * @param filter 键值对过滤编辑器,可以通过实现此接口,完成解析前对键值对的过滤和修改操作,{@code null}表示不过滤 - * @return this - * @throws JSONException 值是无穷数字、键重复抛出异常 - * @since 5.8.0 - */ - public JSONObject setOnce(final String key, final Object value, final Filter> filter) throws JSONException { - return set(key, value, filter, true); - } - /** * 在键和值都为非空的情况下put到JSONObject中 * @@ -272,7 +251,7 @@ public class JSONObject extends MapWrapper implements JSON, JSON * @return this. * @throws JSONException 值是无穷数字 */ - public JSONObject putOpt(final String key, final Object value) throws JSONException { + public JSONObject setOpt(final String key, final Object value) throws JSONException { if (key != null && value != null) { this.set(key, value); } @@ -287,29 +266,12 @@ public class JSONObject extends MapWrapper implements JSON, JSON } /** - * 积累值。类似于set,当key对应value已经存在时,与value组成新的JSONArray.
- * 如果只有一个值,此值就是value,如果多个值,则是添加到新的JSONArray中 - * - * @param key 键 - * @param value 被积累的值 - * @return this. - * @throws JSONException 如果给定键为{@code null}或者键对应的值存在且为非JSONArray - */ - public JSONObject accumulate(final String key, final Object value) throws JSONException { - InternalJSONUtil.testValidity(value); - final Object object = this.getObj(key); - if (object == null) { - this.set(key, value); - } else if (object instanceof JSONArray) { - ((JSONArray) object).set(value); - } else { - this.set(key, JSONUtil.createArray(this.config).set(object).set(value)); - } - return this; - } - - /** - * 追加值,如果key无对应值,就添加一个JSONArray,其元素只有value,如果值已经是一个JSONArray,则添加到值JSONArray中。 + * 追加值. + *
    + *
  • 如果键值对不存在或对应值为{@code null},则value为单独值
  • + *
  • 如果值是一个{@link JSONArray},追加之
  • + *
  • 如果值是一个其他值,则和旧值共同组合为一个{@link JSONArray}
  • + *
* * @param key 键 * @param value 值 @@ -320,11 +282,11 @@ public class JSONObject extends MapWrapper implements JSON, JSON InternalJSONUtil.testValidity(value); final Object object = this.getObj(key); if (object == null) { - this.set(key, new JSONArray(this.config).set(value)); + this.set(key, value); } else if (object instanceof JSONArray) { - this.set(key, ((JSONArray) object).set(value)); + ((JSONArray) object).set(value); } else { - throw new JSONException("JSONObject [" + key + "] is not a JSONArray."); + this.set(key, JSONUtil.createArray(this.config).set(object).set(value)); } return this; } @@ -435,13 +397,13 @@ public class JSONObject extends MapWrapper implements JSON, JSON * @param value 值对象. 可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL. * @param filter 键值对过滤编辑器,可以通过实现此接口,完成解析前对键值对的过滤和修改操作,{@code null}表示不过滤 * @param checkDuplicate 是否检查重复键,如果为{@code true},则出现重复键时抛出{@link JSONException}异常 - * @return this. + * @return 旧值 * @throws JSONException 值是无穷数字抛出此异常 * @since 5.8.0 */ private Object put(String key, Object value, final Filter> filter, final boolean checkDuplicate) throws JSONException { if (null == key) { - return this; + return null; } // 添加前置过滤,通过MutablePair实现过滤、修改键值对等 @@ -453,12 +415,12 @@ public class JSONObject extends MapWrapper implements JSON, JSON value = pair.getValue(); } else { // 键值对被过滤 - return this; + return null; } } final boolean ignoreNullValue = this.config.isIgnoreNullValue(); - if (ObjUtil.isNull(value) && ignoreNullValue) { + if (null == value && ignoreNullValue) { // 忽略值模式下如果值为空清除key return this.remove(key); } else if (checkDuplicate && containsKey(key)) { diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONParser.java b/hutool-json/src/main/java/cn/hutool/json/JSONParser.java index f79c90c5e..15c766b06 100755 --- a/hutool-json/src/main/java/cn/hutool/json/JSONParser.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONParser.java @@ -106,7 +106,7 @@ public class JSONParser { for (; ; ) { if (x.nextClean() == ',') { x.back(); - jsonArray.addRaw(JSONNull.NULL, filter); + jsonArray.addRaw(null, filter); } else { x.back(); jsonArray.addRaw(x.nextValue(), filter); diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONTokener.java b/hutool-json/src/main/java/cn/hutool/json/JSONTokener.java index e86c0c30f..22bd82894 100755 --- a/hutool-json/src/main/java/cn/hutool/json/JSONTokener.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONTokener.java @@ -411,7 +411,7 @@ public class JSONTokener { while (true) { if (this.nextClean() == ',') { this.back(); - jsonArray.add(JSONNull.NULL); + jsonArray.add(null); } else { this.back(); jsonArray.add(this.nextValue()); diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONUtil.java b/hutool-json/src/main/java/cn/hutool/json/JSONUtil.java index f3755ff96..e52fda6b1 100755 --- a/hutool-json/src/main/java/cn/hutool/json/JSONUtil.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONUtil.java @@ -716,7 +716,7 @@ public class JSONUtil { @SuppressWarnings({"rawtypes", "unchecked"}) public static Object wrap(final Object object, final JSONConfig jsonConfig) { if (object == null) { - return jsonConfig.isIgnoreNullValue() ? null : JSONNull.NULL; + return null; } if (object instanceof JSON // || ObjUtil.isNull(object) // @@ -836,22 +836,6 @@ public class JSONUtil { return StrUtil.isWrap(StrUtil.trim(str), '[', ']'); } - /** - * 是否为null对象,null的情况包括: - * - *
-	 * 1. {@code null}
-	 * 2. {@link JSONNull}
-	 * 
- * - * @param obj 对象 - * @return 是否为null - * @since 4.5.7 - */ - public static boolean isNull(final Object obj) { - return null == obj || obj instanceof JSONNull; - } - /** * XML转JSONObject
* 转换过程中一些信息可能会丢失,JSON中无法区分节点和属性,相同的节点将被处理为JSONArray。 diff --git a/hutool-json/src/main/java/cn/hutool/json/serialize/JSONWriter.java b/hutool-json/src/main/java/cn/hutool/json/serialize/JSONWriter.java index 9fde0e255..8ddb3876c 100755 --- a/hutool-json/src/main/java/cn/hutool/json/serialize/JSONWriter.java +++ b/hutool-json/src/main/java/cn/hutool/json/serialize/JSONWriter.java @@ -14,7 +14,6 @@ import cn.hutool.json.JSON; import cn.hutool.json.JSONArray; import cn.hutool.json.JSONConfig; import cn.hutool.json.JSONException; -import cn.hutool.json.JSONNull; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONString; import cn.hutool.json.JSONUtil; @@ -96,6 +95,7 @@ public class JSONWriter extends Writer { * @return this */ public JSONWriter beginObj() { + //noinspection resource writeRaw(CharUtil.DELIM_START); return this; } @@ -106,6 +106,7 @@ public class JSONWriter extends Writer { * @return this */ public JSONWriter beginArray() { + //noinspection resource writeRaw(CharUtil.BRACKET_START); arrayMode = true; return this; @@ -118,7 +119,9 @@ public class JSONWriter extends Writer { */ public JSONWriter end() { // 换行缩进 + //noinspection resource writeLF().writeSpace(indent); + //noinspection resource writeRaw(arrayMode ? CharUtil.BRACKET_END : CharUtil.DELIM_END); flush(); arrayMode = false; @@ -135,22 +138,24 @@ public class JSONWriter extends Writer { */ public JSONWriter writeKey(final String key) { if (needSeparator) { + //noinspection resource writeRaw(CharUtil.COMMA); } // 换行缩进 + //noinspection resource writeLF().writeSpace(indentFactor + indent); return writeRaw(JSONUtil.quote(key)); } /** * 写出值,自动处理分隔符和缩进,自动判断类型,并根据不同类型写出特定格式的值
- * 如果写出的值为{@code null}或者{@link JSONNull},且配置忽略null,则跳过。 + * 如果写出的值为{@code null},且配置忽略null,则跳过。 * * @param value 值 * @return this */ public JSONWriter writeValue(final Object value) { - if(JSONUtil.isNull(value) && config.isIgnoreNullValue()){ + if (null == value && config.isIgnoreNullValue()) { return this; } return writeValueDirect(value); @@ -159,16 +164,17 @@ public class JSONWriter extends Writer { /** * 写出字段名及字段值,如果字段值是{@code null}且忽略null值,则不写出任何内容 * - * @param key 字段名 + * @param key 字段名 * @param value 字段值 * @return this * @since 5.7.6 */ - public JSONWriter writeField(final String key, final Object value){ - if(JSONUtil.isNull(value) && config.isIgnoreNullValue()){ + public JSONWriter writeField(final String key, final Object value) { + if (null == value && config.isIgnoreNullValue()) { return this; } + //noinspection resource return writeKey(key).writeValueDirect(value); } @@ -192,6 +198,7 @@ public class JSONWriter extends Writer { } // ------------------------------------------------------------------------------ Private methods + /** * 写出值,自动处理分隔符和缩进,自动判断类型,并根据不同类型写出特定格式的值 * @@ -201,11 +208,14 @@ public class JSONWriter extends Writer { private JSONWriter writeValueDirect(final Object value) { if (arrayMode) { if (needSeparator) { + //noinspection resource writeRaw(CharUtil.COMMA); } // 换行缩进 + //noinspection resource writeLF().writeSpace(indentFactor + indent); } else { + //noinspection resource writeRaw(CharUtil.COLON).writeSpace(1); } needSeparator = true; @@ -220,24 +230,26 @@ public class JSONWriter extends Writer { */ private JSONWriter writeObjValue(final Object value) { final int indent = indentFactor + this.indent; - if (value == null || value instanceof JSONNull) { - writeRaw(JSONNull.NULL.toString()); + if (value == null) { + //noinspection resource + writeRaw(StrUtil.NULL); } else if (value instanceof JSON) { ((JSON) value).write(writer, indentFactor, indent); } else if (value instanceof Map || value instanceof Map.Entry) { new JSONObject(value).write(writer, indentFactor, indent); } else if (value instanceof Iterable || value instanceof Iterator || ArrayUtil.isArray(value)) { - if(value instanceof byte[]){ + if (value instanceof byte[]) { // issue#I59LW4 // json内容中的bytes默认转为Base64 writeStrValue(Base64.encode((byte[]) value)); - }else{ + } else { new JSONArray(value).write(writer, indentFactor, indent); } } else if (value instanceof Number) { writeNumberValue((Number) value); } else if (value instanceof Date || value instanceof Calendar || value instanceof TemporalAccessor) { final String format = (null == config) ? null : config.getDateFormat(); + //noinspection resource writeRaw(formatDate(value, format)); } else if (value instanceof Boolean) { writeBooleanValue((Boolean) value); @@ -260,6 +272,7 @@ public class JSONWriter extends Writer { private void writeNumberValue(final Number number) { // since 5.6.2可配置是否去除末尾多余0,例如如果为true,5.0返回5 final boolean isStripTrailingZeros = null == config || config.isStripTrailingZeros(); + //noinspection resource writeRaw(NumberUtil.toStr(number, isStripTrailingZeros)); } @@ -269,6 +282,7 @@ public class JSONWriter extends Writer { * @param value Boolean值 */ private void writeBooleanValue(final Boolean value) { + //noinspection resource writeRaw(value.toString()); } @@ -287,6 +301,7 @@ public class JSONWriter extends Writer { throw new JSONException(e); } if (null != valueStr) { + //noinspection resource writeRaw(valueStr); } else { writeStrValue(jsonString.toString()); @@ -317,6 +332,7 @@ public class JSONWriter extends Writer { private void writeSpace(final int count) { if (indentFactor > 0) { for (int i = 0; i < count; i++) { + //noinspection resource writeRaw(CharUtil.SPACE); } } @@ -329,6 +345,7 @@ public class JSONWriter extends Writer { */ private JSONWriter writeLF() { if (indentFactor > 0) { + //noinspection resource writeRaw(CharUtil.LF); } return this; diff --git a/hutool-json/src/main/java/cn/hutool/json/xml/JSONXMLParser.java b/hutool-json/src/main/java/cn/hutool/json/xml/JSONXMLParser.java index 28f2ab225..d50a4bef7 100644 --- a/hutool-json/src/main/java/cn/hutool/json/xml/JSONXMLParser.java +++ b/hutool-json/src/main/java/cn/hutool/json/xml/JSONXMLParser.java @@ -1,5 +1,6 @@ package cn.hutool.json.xml; +import cn.hutool.core.text.StrUtil; import cn.hutool.json.InternalJSONUtil; import cn.hutool.json.JSONException; import cn.hutool.json.JSONObject; @@ -63,7 +64,7 @@ public class JSONXMLParser { if (x.next() == '[') { string = x.nextCDATA(); if (string.length() > 0) { - context.accumulate("content", string); + context.append("content", string); } return false; } @@ -126,10 +127,10 @@ public class JSONXMLParser { if (!(token instanceof String)) { throw x.syntaxError("Missing value"); } - jsonobject.accumulate(string, keepStrings ? token : InternalJSONUtil.stringToValue((String) token)); + jsonobject.append(string, keepStrings ? token : InternalJSONUtil.stringToValue((String) token)); token = null; } else { - jsonobject.accumulate(string, ""); + jsonobject.append(string, ""); } } else if (token == XML.SLASH) { @@ -138,9 +139,9 @@ public class JSONXMLParser { throw x.syntaxError("Misshaped tag"); } if (jsonobject.size() > 0) { - context.accumulate(tagName, jsonobject); + context.append(tagName, jsonobject); } else { - context.accumulate(tagName, ""); + context.append(tagName, StrUtil.EMPTY); } return false; @@ -156,18 +157,18 @@ public class JSONXMLParser { } else if (token instanceof String) { string = (String) token; if (string.length() > 0) { - jsonobject.accumulate("content", keepStrings ? token : InternalJSONUtil.stringToValue(string)); + jsonobject.append("content", keepStrings ? token : InternalJSONUtil.stringToValue(string)); } } else if (token == XML.LT) { // Nested element if (parse(x, jsonobject, tagName, keepStrings)) { if (jsonobject.size() == 0) { - context.accumulate(tagName, ""); + context.append(tagName, ""); } else if (jsonobject.size() == 1 && jsonobject.get("content") != null) { - context.accumulate(tagName, jsonobject.get("content")); + context.append(tagName, jsonobject.get("content")); } else { - context.accumulate(tagName, jsonobject); + context.append(tagName, jsonobject); } return false; } diff --git a/hutool-json/src/test/java/cn/hutool/json/JSONArrayTest.java b/hutool-json/src/test/java/cn/hutool/json/JSONArrayTest.java index 5258c1479..a88bfb8e2 100755 --- a/hutool-json/src/test/java/cn/hutool/json/JSONArrayTest.java +++ b/hutool-json/src/test/java/cn/hutool/json/JSONArrayTest.java @@ -166,7 +166,7 @@ public class JSONArrayTest { @Test public void toListWithNullTest() { final String json = "[null,{'akey':'avalue','bkey':'bvalue'}]"; - final JSONArray ja = JSONUtil.parseArray(json); + final JSONArray ja = JSONUtil.parseArray(json, JSONConfig.of().setIgnoreNullValue(false)); final List list = ja.toList(KeyBean.class); Assert.assertNull(list.get(0)); @@ -218,8 +218,13 @@ public class JSONArrayTest { @Test public void putToIndexTest(){ - final JSONArray jsonArray = new JSONArray(); - jsonArray.put(3, "test"); + JSONArray jsonArray = new JSONArray(); + jsonArray.set(3, "test"); + // 默认忽略null值,因此空位无值,只有一个值 + Assert.assertEquals(1, jsonArray.size()); + + jsonArray = new JSONArray(JSONConfig.of().setIgnoreNullValue(false)); + jsonArray.set(3, "test"); // 第三个位置插入值,0~2都是null Assert.assertEquals(4, jsonArray.size()); } diff --git a/hutool-json/src/test/java/cn/hutool/json/JSONNullTest.java b/hutool-json/src/test/java/cn/hutool/json/JSONNullTest.java index 0883ed768..9f3783449 100644 --- a/hutool-json/src/test/java/cn/hutool/json/JSONNullTest.java +++ b/hutool-json/src/test/java/cn/hutool/json/JSONNullTest.java @@ -12,9 +12,9 @@ public class JSONNullTest { " \"device_status_date\": null,\n" + " \"imsi\": null,\n" + " \"act_date\": \"2021-07-23T06:23:26.000+00:00\"}"); - Assert.assertEquals(JSONNull.class, bodyjson.get("device_model").getClass()); - Assert.assertEquals(JSONNull.class, bodyjson.get("device_status_date").getClass()); - Assert.assertEquals(JSONNull.class, bodyjson.get("imsi").getClass()); + Assert.assertNull(bodyjson.get("device_model")); + Assert.assertNull(bodyjson.get("device_status_date")); + Assert.assertNull(bodyjson.get("imsi")); bodyjson.getConfig().setIgnoreNullValue(true); Assert.assertEquals("{\"act_date\":\"2021-07-23T06:23:26.000+00:00\"}", bodyjson.toString()); @@ -31,4 +31,26 @@ public class JSONNullTest { Assert.assertFalse(bodyjson.containsKey("device_status_date")); Assert.assertFalse(bodyjson.containsKey("imsi")); } + + @Test + public void setNullTest(){ + // 忽略null + String json1 = JSONUtil.createObj().set("key1", null).toString(); + Assert.assertEquals("{}", json1); + + // 不忽略null + json1 = JSONUtil.createObj(JSONConfig.of().setIgnoreNullValue(false)).set("key1", null).toString(); + Assert.assertEquals("{\"key1\":null}", json1); + } + + @Test + public void setNullOfJSONArrayTest(){ + // 忽略null + String json1 = JSONUtil.createArray().set(null).toString(); + Assert.assertEquals("[]", json1); + + // 不忽略null + json1 = JSONUtil.createArray(JSONConfig.of().setIgnoreNullValue(false)).set(null).toString(); + Assert.assertEquals("[null]", json1); + } } 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 13b761231..50596ac2e 100755 --- a/hutool-json/src/test/java/cn/hutool/json/JSONObjectTest.java +++ b/hutool-json/src/test/java/cn/hutool/json/JSONObjectTest.java @@ -116,7 +116,7 @@ public class JSONObjectTest { Assert.assertEquals(jsonObject.get("d"), true); Assert.assertTrue(jsonObject.containsKey("e")); - Assert.assertEquals(jsonObject.get("e"), JSONNull.NULL); + Assert.assertNull(jsonObject.get("e")); } @Test @@ -460,7 +460,7 @@ public class JSONObjectTest { json.append("date", DateUtil.parse("2020-06-05 11:16:11")); json.append("bbb", "222"); json.append("aaa", "123"); - Assert.assertEquals("{\"date\":[\"2020-06-05 11:16:11\"],\"bbb\":[\"222\"],\"aaa\":[\"123\"]}", json.toString()); + Assert.assertEquals("{\"date\":\"2020-06-05 11:16:11\",\"bbb\":\"222\",\"aaa\":\"123\"}", json.toString()); } @Test @@ -612,14 +612,14 @@ public class JSONObjectTest { } @Test - public void accumulateTest() { - final JSONObject jsonObject = JSONUtil.createObj().accumulate("key1", "value1"); + public void appendTest() { + final JSONObject jsonObject = JSONUtil.createObj().append("key1", "value1"); Assert.assertEquals("{\"key1\":\"value1\"}", jsonObject.toString()); - jsonObject.accumulate("key1", "value2"); + jsonObject.append("key1", "value2"); Assert.assertEquals("{\"key1\":[\"value1\",\"value2\"]}", jsonObject.toString()); - jsonObject.accumulate("key1", "value3"); + jsonObject.append("key1", "value3"); Assert.assertEquals("{\"key1\":[\"value1\",\"value2\",\"value3\"]}", jsonObject.toString()); }