diff --git a/hutool-json/src/main/java/org/dromara/hutool/json/JSONObject.java b/hutool-json/src/main/java/org/dromara/hutool/json/JSONObject.java index a1702fc8b..d58735e19 100644 --- a/hutool-json/src/main/java/org/dromara/hutool/json/JSONObject.java +++ b/hutool-json/src/main/java/org/dromara/hutool/json/JSONObject.java @@ -195,12 +195,13 @@ public class JSONObject extends MapWrapper implements JSON, JSON /** * 根据lambda的方法引用,获取 + * * @param func 方法引用 - * @param

参数类型 - * @param 返回值类型 + * @param

参数类型 + * @param 返回值类型 * @return 获取表达式对应属性和返回的对象 */ - public T get(final SerFunction func){ + public T get(final SerFunction func) { final LambdaInfo lambdaInfo = LambdaUtil.resolve(func); return get(lambdaInfo.getFieldName(), lambdaInfo.getReturnType()); } @@ -314,6 +315,38 @@ public class JSONObject extends MapWrapper implements JSON, JSON * @throws JSONException 如果给定键为{@code null}或者键对应的值存在且为非JSONArray */ public JSONObject append(final String key, final Object value) throws JSONException { + return append(key, value, null); + } + + /** + * 追加值. + *

+ * + * @param key 键 + * @param value 值 + * @param predicate 键值对过滤编辑器,可以通过实现此接口,完成解析前对键值对的过滤和修改操作,{@code null}表示不过滤,{@link Predicate#test(Object)}为{@code true}保留 + * @return this. + * @throws JSONException 如果给定键为{@code null}或者键对应的值存在且为非JSONArray + * @since 6.0.0 + */ + public JSONObject append(String key, Object value, final Predicate> predicate) throws JSONException { + // 添加前置过滤,通过MutablePair实现过滤、修改键值对等 + if (null != predicate) { + final MutableEntry pair = new MutableEntry<>(key, value); + if (predicate.test(pair)) { + // 使用修改后的键值对 + key = pair.getKey(); + value = pair.getValue(); + } else { + // 键值对被过滤 + return this; + } + } + final Object object = this.getObj(key); if (object == null) { this.set(key, value); @@ -396,7 +429,7 @@ public class JSONObject extends MapWrapper implements JSON, JSON @Override public Writer write(final Writer writer, final int indentFactor, final int indent, final Predicate> predicate) throws JSONException { final JSONWriter jsonWriter = JSONWriter.of(writer, indentFactor, indent, config) - .beginObj(); + .beginObj(); this.forEach((key, value) -> jsonWriter.writeField(new MutableEntry<>(key, value), predicate)); jsonWriter.end(); // 此处不关闭Writer,考虑writer后续还需要填内容 diff --git a/hutool-json/src/main/java/org/dromara/hutool/json/mapper/JSONObjectMapper.java b/hutool-json/src/main/java/org/dromara/hutool/json/mapper/JSONObjectMapper.java index a102aa19f..762de4325 100644 --- a/hutool-json/src/main/java/org/dromara/hutool/json/mapper/JSONObjectMapper.java +++ b/hutool-json/src/main/java/org/dromara/hutool/json/mapper/JSONObjectMapper.java @@ -20,15 +20,10 @@ import org.dromara.hutool.core.io.IoUtil; import org.dromara.hutool.core.lang.mutable.MutableEntry; import org.dromara.hutool.core.reflect.method.MethodUtil; import org.dromara.hutool.core.text.StrUtil; -import org.dromara.hutool.json.InternalJSONUtil; -import org.dromara.hutool.json.JSONArray; -import org.dromara.hutool.json.JSONException; -import org.dromara.hutool.json.JSONObject; -import org.dromara.hutool.json.JSONParser; -import org.dromara.hutool.json.JSONTokener; -import org.dromara.hutool.json.xml.JSONXMLUtil; +import org.dromara.hutool.json.*; import org.dromara.hutool.json.serialize.GlobalSerializeMapping; import org.dromara.hutool.json.serialize.JSONSerializer; +import org.dromara.hutool.json.xml.JSONXMLParser; import org.dromara.hutool.json.xml.ParseConfig; import java.io.InputStream; @@ -171,7 +166,8 @@ public class JSONObjectMapper { final String jsonStr = StrUtil.trim(source); if (StrUtil.startWith(jsonStr, '<')) { // 可能为XML - JSONXMLUtil.toJSONObject(jsonStr, jsonObject, ParseConfig.of()); + //JSONXMLUtil.toJSONObject(jsonStr, jsonObject, ParseConfig.of()); + JSONXMLParser.of(ParseConfig.of(), this.predicate).parseJSONObject(jsonStr, jsonObject); return; } mapFromTokener(new JSONTokener(StrUtil.trim(source), jsonObject.config()), jsonObject); diff --git a/hutool-json/src/main/java/org/dromara/hutool/json/xml/JSONXMLParser.java b/hutool-json/src/main/java/org/dromara/hutool/json/xml/JSONXMLParser.java index 524829c4a..9d22f1522 100644 --- a/hutool-json/src/main/java/org/dromara/hutool/json/xml/JSONXMLParser.java +++ b/hutool-json/src/main/java/org/dromara/hutool/json/xml/JSONXMLParser.java @@ -12,6 +12,7 @@ package org.dromara.hutool.json.xml; +import org.dromara.hutool.core.lang.mutable.MutableEntry; import org.dromara.hutool.core.text.CharUtil; import org.dromara.hutool.core.text.StrUtil; import org.dromara.hutool.core.xml.XmlConstants; @@ -19,6 +20,8 @@ import org.dromara.hutool.json.JSONException; import org.dromara.hutool.json.JSONObject; import org.dromara.hutool.json.mapper.JSONValueMapper; +import java.util.function.Predicate; + /** * XML解析器,将XML解析为JSON对象 * @@ -27,19 +30,43 @@ import org.dromara.hutool.json.mapper.JSONValueMapper; */ public class JSONXMLParser { + /** + * 创建XML解析器 + * + * @param parseConfig 解析选项 + * @param predicate 键值对过滤编辑器,可以通过实现此接口,完成解析前对键值对的过滤和修改操作,{@link Predicate#test(Object)}为{@code true}保留 + * @return JSONXMLParser + */ + public static JSONXMLParser of(final ParseConfig parseConfig, final Predicate> predicate) { + return new JSONXMLParser(parseConfig, predicate); + } + + private final ParseConfig parseConfig; + private final Predicate> predicate; + + /** + * 构造 + * + * @param parseConfig 解析选项 + * @param predicate 键值对过滤编辑器,可以通过实现此接口,完成解析前对键值对的过滤和修改操作,{@link Predicate#test(Object)}为{@code true}保留 + */ + public JSONXMLParser(final ParseConfig parseConfig, final Predicate> predicate) { + this.parseConfig = parseConfig; + this.predicate = predicate; + } + /** * 转换XML为JSONObject * 转换过程中一些信息可能会丢失,JSON中无法区分节点和属性,相同的节点将被处理为JSONArray。 * * @param xmlStr XML字符串 * @param jo JSONObject - * @param parseConfig 解析选项 * @throws JSONException 解析异常 */ - public static void parseJSONObject(final String xmlStr, final JSONObject jo, final ParseConfig parseConfig) throws JSONException { + public void parseJSONObject(final String xmlStr, final JSONObject jo) throws JSONException { final XMLTokener x = new XMLTokener(xmlStr, jo.config()); while (x.more() && x.skipPast("<")) { - parse(x, jo, null, parseConfig, 0); + parse(x, jo, null, 0); } } @@ -49,13 +76,11 @@ public class JSONXMLParser { * @param x {@link XMLTokener} * @param context {@link JSONObject} * @param name 标签名,null表示从根标签开始解析 - * @param parseConfig 解析选项 * @param currentNestingDepth 当前层级 * @return {@code true}表示解析完成 * @throws JSONException JSON异常 */ - private static boolean parse(final XMLTokener x, final JSONObject context, final String name, - final ParseConfig parseConfig, final int currentNestingDepth) throws JSONException { + private boolean parse(final XMLTokener x, final JSONObject context, final String name, final int currentNestingDepth) throws JSONException { final char c; int i; final JSONObject jsonobject; @@ -155,9 +180,9 @@ public class JSONXMLParser { throw x.syntaxError("Misshaped tag"); } if (!jsonobject.isEmpty()) { - context.append(tagName, jsonobject); + context.append(tagName, jsonobject, this.predicate); } else { - context.append(tagName, StrUtil.EMPTY); + context.append(tagName, StrUtil.EMPTY, this.predicate); } return false; @@ -185,13 +210,13 @@ public class JSONXMLParser { } // Nested element - if (parse(x, jsonobject, tagName, parseConfig, currentNestingDepth + 1)) { + if (parse(x, jsonobject, tagName, currentNestingDepth + 1)) { if (jsonobject.isEmpty()) { - context.append(tagName, StrUtil.EMPTY); + context.append(tagName, StrUtil.EMPTY, this.predicate); } else if (jsonobject.size() == 1 && jsonobject.get("content") != null) { - context.append(tagName, jsonobject.get("content")); + context.append(tagName, jsonobject.get("content"), this.predicate); } else { - context.append(tagName, jsonobject); + context.append(tagName, jsonobject, this.predicate); } return false; } diff --git a/hutool-json/src/main/java/org/dromara/hutool/json/xml/JSONXMLUtil.java b/hutool-json/src/main/java/org/dromara/hutool/json/xml/JSONXMLUtil.java index 083a2a56a..3127857b5 100644 --- a/hutool-json/src/main/java/org/dromara/hutool/json/xml/JSONXMLUtil.java +++ b/hutool-json/src/main/java/org/dromara/hutool/json/xml/JSONXMLUtil.java @@ -64,7 +64,7 @@ public class JSONXMLUtil { * @since 5.3.1 */ public static JSONObject toJSONObject(final String xmlStr, final JSONObject jo, final ParseConfig parseConfig) throws JSONException { - JSONXMLParser.parseJSONObject(xmlStr, jo, parseConfig); + JSONXMLParser.of(parseConfig, null).parseJSONObject(xmlStr, jo); return jo; } diff --git a/hutool-json/src/test/java/org/dromara/hutool/json/IssueI9DX5HTest.java b/hutool-json/src/test/java/org/dromara/hutool/json/IssueI9DX5HTest.java new file mode 100644 index 000000000..ab89efc48 --- /dev/null +++ b/hutool-json/src/test/java/org/dromara/hutool/json/IssueI9DX5HTest.java @@ -0,0 +1,20 @@ +package org.dromara.hutool.json; + +import org.dromara.hutool.core.text.StrUtil; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class IssueI9DX5HTest { + + @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") + @Test + void xmlToJSONTest() { + final String xml = "你好"; + final JSONObject jsonObject = new JSONObject(xml, JSONConfig.of(), entry -> { + entry.setKey(StrUtil.toUnderlineCase(entry.getKey())); + return true; + }); + + Assertions.assertEquals("{\"good_msg\":\"你好\"}", jsonObject.toString()); + } +}