From 75f9a66998823c8e26224c711ff4438c4d730b50 Mon Sep 17 00:00:00 2001 From: Looly Date: Sun, 4 Aug 2024 12:03:33 +0800 Subject: [PATCH] fix code --- .../org/dromara/hutool/json/JSONParser.java | 127 +++++++++++++++- .../org/dromara/hutool/json/JSONTokener.java | 88 ++--------- .../hutool/json/convert/JSONConverter.java | 96 +++++++----- .../hutool/json/mapper/JSONArrayMapper.java | 27 ++-- .../hutool/json/mapper/JSONObjectMapper.java | 18 ++- .../hutool/json/xml/JSONXMLParser.java | 2 +- .../dromara/hutool/json/xml/XMLTokener.java | 5 +- .../org/dromara/hutool/json/JSONUtilTest.java | 142 ++++++++++-------- 8 files changed, 302 insertions(+), 203 deletions(-) diff --git a/hutool-json/src/main/java/org/dromara/hutool/json/JSONParser.java b/hutool-json/src/main/java/org/dromara/hutool/json/JSONParser.java index 7eb63b151..5b4055a2b 100644 --- a/hutool-json/src/main/java/org/dromara/hutool/json/JSONParser.java +++ b/hutool-json/src/main/java/org/dromara/hutool/json/JSONParser.java @@ -30,14 +30,20 @@ import java.util.function.Predicate; */ public class JSONParser { + /** + * JSON配置 + */ + private final JSONConfig config; + /** * 创建JSONParser * * @param tokener {@link JSONTokener} + * @param config JSON配置 * @return JSONParser */ - public static JSONParser of(final JSONTokener tokener) { - return new JSONParser(tokener); + public static JSONParser of(final JSONTokener tokener, final JSONConfig config) { + return new JSONParser(tokener, config); } private final JSONTokener tokener; @@ -46,9 +52,29 @@ public class JSONParser { * 构造 * * @param tokener {@link JSONTokener} + * @param config JSON配置 */ - public JSONParser(final JSONTokener tokener) { + public JSONParser(final JSONTokener tokener, final JSONConfig config) { this.tokener = tokener; + this.config = config; + } + + /** + * 获取{@link JSONTokener} + * + * @return {@link JSONTokener} + */ + public JSONTokener getTokener() { + return this.tokener; + } + + /** + * 是否结束 + * + * @return 是否结束 + */ + public boolean end() { + return this.tokener.end(); } // region parseTo @@ -79,12 +105,12 @@ public class JSONParser { return; case '{': case '[': - if(prev=='{') { + if (prev == '{') { throw tokener.syntaxError("A JSONObject can not directly nest another JSONObject or JSONArray."); } default: tokener.back(); - key = tokener.nextValue(true).toString(); + key = nextValue(true).toString(); } // The key is followed by ':'. @@ -94,7 +120,7 @@ public class JSONParser { throw tokener.syntaxError("Expected a ':' after a key"); } - jsonObject.set(key, tokener.nextValue(false), predicate); + jsonObject.set(key, nextValue(false), predicate); // Pairs are separated by ','. @@ -136,7 +162,7 @@ public class JSONParser { jsonArray.addRaw(null, predicate); } else { x.back(); - jsonArray.addRaw(x.nextValue(false), predicate); + jsonArray.addRaw(nextValue(false), predicate); } switch (x.nextClean()) { case CharUtil.COMMA: @@ -154,4 +180,91 @@ public class JSONParser { } } // endregion + + /** + * 获得下一个值,值类型可以是Boolean, Double, Integer, JSONArray, JSONObject, Long, or String + * + * @param getOnlyStringValue 是否只获取String值 + * @return Boolean, Double, Integer, JSONArray, JSONObject, Long, or String + * @throws JSONException 语法错误 + */ + public Object nextValue(final boolean getOnlyStringValue) throws JSONException { + return nextValue(getOnlyStringValue, (token, tokener, config) -> { + switch (token) { + case '{': + try { + return new JSONObject(this, config); + } catch (final StackOverflowError e) { + throw new JSONException("JSONObject depth too large to process.", e); + } + case '[': + try { + return new JSONArray(this, config); + } catch (final StackOverflowError e) { + throw new JSONException("JSONObject depth too large to process.", e); + } + } + throw new JSONException("Unsupported object build for token {}", token); + }); + } + + /** + * 获得下一个值,值类型可以是Boolean, Double, Integer, JSONArray, JSONObject, Long, or String + * + * @param getOnlyStringValue 是否只获取String值 + * @param objectBuilder JSON对象构建器 + * @return Boolean, Double, Integer, JSONArray, JSONObject, Long, or String + * @throws JSONException 语法错误 + */ + public Object nextValue(final boolean getOnlyStringValue, final ObjectBuilder objectBuilder) throws JSONException { + final JSONTokener tokener = this.tokener; + char c = tokener.nextClean(); + switch (c) { + case '"': + case '\'': + return tokener.nextString(c); + case '{': + case '[': + if (getOnlyStringValue) { + throw tokener.syntaxError("String value must not begin with '{'"); + } + tokener.back(); + return objectBuilder.build(c, tokener, this.config); + } + + /* + * Handle unquoted text. This could be the values true, false, or null, or it can be a number. + * An implementation (such as this one) is allowed to also accept non-standard forms. Accumulate + * characters until we reach the end of the text or a formatting character. + */ + + final StringBuilder sb = new StringBuilder(); + while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) { + sb.append(c); + c = tokener.next(); + } + tokener.back(); + + final String valueString = sb.toString().trim(); + if (valueString.isEmpty()) { + throw tokener.syntaxError("Missing value"); + } + return getOnlyStringValue ? valueString : InternalJSONUtil.parseValueFromString(valueString); + } + + /** + * 对象构建抽象,通过实现此接口,从{@link JSONTokener}解析值并构建指定对象 + */ + @FunctionalInterface + public interface ObjectBuilder { + /** + * 构建 + * + * @param token 符号表示,用于区分对象类型 + * @param tokener {@link JSONTokener} + * @param config {@link JSONConfig} + * @return 构建的对象 + */ + Object build(char token, JSONTokener tokener, JSONConfig config); + } } diff --git a/hutool-json/src/main/java/org/dromara/hutool/json/JSONTokener.java b/hutool-json/src/main/java/org/dromara/hutool/json/JSONTokener.java index a2692366c..a29af097a 100644 --- a/hutool-json/src/main/java/org/dromara/hutool/json/JSONTokener.java +++ b/hutool-json/src/main/java/org/dromara/hutool/json/JSONTokener.java @@ -29,6 +29,11 @@ import java.io.StringReader; */ public class JSONTokener extends ReaderWrapper { + /** + * 定义结束(End of stream)为:0 + */ + public static final int EOF = 0; + private long character; /** * 是否结尾 End of stream @@ -51,41 +56,33 @@ public class JSONTokener extends ReaderWrapper { */ private boolean usePrevious; - /** - * JSON配置 - */ - private final JSONConfig config; - // ------------------------------------------------------------------------------------ Constructor start /** * 从InputStream中构建,使用UTF-8编码 * * @param inputStream InputStream - * @param config JSON配置 * @throws JSONException JSON异常,包装IO异常 */ - public JSONTokener(final InputStream inputStream, final JSONConfig config) throws JSONException { - this(IoUtil.toUtf8Reader(inputStream), config); + public JSONTokener(final InputStream inputStream) throws JSONException { + this(IoUtil.toUtf8Reader(inputStream)); } /** * 从字符串中构建 * - * @param s JSON字符串 - * @param config JSON配置 + * @param s JSON字符串 */ - public JSONTokener(final CharSequence s, final JSONConfig config) { - this(new StringReader(Assert.notBlank(s).toString()), config); + public JSONTokener(final CharSequence s) { + this(new StringReader(Assert.notBlank(s).toString())); } /** * 从Reader中构建 * * @param reader Reader - * @param config JSON配置 */ - public JSONTokener(final Reader reader, final JSONConfig config) { + public JSONTokener(final Reader reader) { super(IoUtil.toMarkSupport(Assert.notNull(reader))); this.eof = false; this.usePrevious = false; @@ -93,7 +90,6 @@ public class JSONTokener extends ReaderWrapper { this.index = 0; this.character = 1; this.line = 1; - this.config = config; } // ------------------------------------------------------------------------------------ Constructor end @@ -152,9 +148,9 @@ public class JSONTokener extends ReaderWrapper { throw new JSONException(exception); } - if (c <= 0) { // End of stream + if (c <= EOF) { // End of stream this.eof = true; - c = 0; + c = EOF; } } this.index += 1; @@ -183,9 +179,10 @@ public class JSONTokener extends ReaderWrapper { /** * 获取16进制unicode转义符对应的字符值,如: *
{@code '4f60' -> '你'}
+ * * @return 字符 */ - public char nextUnicode(){ + public char nextUnicode() { return (char) NumberUtil.parseInt(next(4), 16); } @@ -332,61 +329,6 @@ public class JSONTokener extends ReaderWrapper { } } - /** - * 获得下一个值,值类型可以是Boolean, Double, Integer, JSONArray, JSONObject, Long, or String - * - * @param getOnlyStringValue 是否只获取String值 - * @return Boolean, Double, Integer, JSONArray, JSONObject, Long, or String - * @throws JSONException 语法错误 - */ - public Object nextValue(final boolean getOnlyStringValue) throws JSONException { - char c = this.nextClean(); - switch (c) { - case '"': - case '\'': - return this.nextString(c); - case '{': - if (getOnlyStringValue) { - throw this.syntaxError("String value must not begin with '{'"); - } - this.back(); - try { - return new JSONObject(this, this.config); - } catch (final StackOverflowError e) { - throw new JSONException("JSONObject depth too large to process.", e); - } - case '[': - if (getOnlyStringValue) { - throw this.syntaxError("String value must not begin with '['"); - } - this.back(); - try { - return new JSONArray(this, this.config); - } catch (final StackOverflowError e) { - throw new JSONException("JSONArray depth too large to process.", e); - } - } - - /* - * Handle unquoted text. This could be the values true, false, or null, or it can be a number. - * An implementation (such as this one) is allowed to also accept non-standard forms. Accumulate - * characters until we reach the end of the text or a formatting character. - */ - - final StringBuilder sb = new StringBuilder(); - while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) { - sb.append(c); - c = this.next(); - } - this.back(); - - final String valueString = sb.toString().trim(); - if (valueString.isEmpty()) { - throw this.syntaxError("Missing value"); - } - return getOnlyStringValue ? valueString : InternalJSONUtil.parseValueFromString(valueString); - } - /** * Skip characters until the next character is the requested character. If the requested character is not found, no characters are skipped. 在遇到指定字符前,跳过其它字符。如果字符未找到,则不跳过任何字符。 * diff --git a/hutool-json/src/main/java/org/dromara/hutool/json/convert/JSONConverter.java b/hutool-json/src/main/java/org/dromara/hutool/json/convert/JSONConverter.java index 7ce043539..ff4a73786 100644 --- a/hutool-json/src/main/java/org/dromara/hutool/json/convert/JSONConverter.java +++ b/hutool-json/src/main/java/org/dromara/hutool/json/convert/JSONConverter.java @@ -103,14 +103,14 @@ public class JSONConverter implements Converter, Serializable { // 对象转JSON final Class targetClass = TypeUtil.getClass(targetType); - if(null != targetClass){ + if (null != targetClass) { if (JSON.class.isAssignableFrom(targetClass)) { return toJSON(value); } // 自定义日期格式 - if(Date.class.isAssignableFrom(targetClass) || TemporalAccessor.class.isAssignableFrom(targetClass)){ + if (Date.class.isAssignableFrom(targetClass) || TemporalAccessor.class.isAssignableFrom(targetClass)) { final Object date = toDateWithFormat(targetClass, value); - if(null != date){ + if (null != date) { return date; } } @@ -120,7 +120,7 @@ public class JSONConverter implements Converter, Serializable { } /** - * 实现Object对象转换为{@link JSON},支持的对象: + * 实现Object对象转换为JSON对象,根据RFC8259规范,支持的对象: *