diff --git a/hutool-json/src/main/java/org/dromara/hutool/json/InternalJSONUtil.java b/hutool-json/src/main/java/org/dromara/hutool/json/InternalJSONUtil.java index cbc15f16d..9a3d213ed 100644 --- a/hutool-json/src/main/java/org/dromara/hutool/json/InternalJSONUtil.java +++ b/hutool-json/src/main/java/org/dromara/hutool/json/InternalJSONUtil.java @@ -62,6 +62,22 @@ public final class InternalJSONUtil { return Boolean.FALSE; } + return parseNumberOrString(string); + } + + /** + * 尝试转换字符串为number or null,无法转换返回String
+ * 此方法用于解析JSON字符串时,将字符串中的值转换为JSON值对象 + * + * @param string A String. + * @return A simple JSON value. + */ + public static Object parseNumberOrString(final String string) { + // null处理 + if (StrUtil.isEmpty(string)) { + return null; + } + // Number处理 final char b = string.charAt(0); if ((b >= '0' && b <= '9') || b == '-') { @@ -83,7 +99,8 @@ public final class InternalJSONUtil { } } - // 其它情况返回原String值下 + // 无法解析的超大数字,直接返回字符串 + // "xxx"这种直接字符串形式的值,直接返回 return string; } diff --git a/hutool-json/src/main/java/org/dromara/hutool/json/JSONFactory.java b/hutool-json/src/main/java/org/dromara/hutool/json/JSONFactory.java index c04568715..c4e2c54bd 100644 --- a/hutool-json/src/main/java/org/dromara/hutool/json/JSONFactory.java +++ b/hutool-json/src/main/java/org/dromara/hutool/json/JSONFactory.java @@ -155,7 +155,7 @@ public class JSONFactory { * @return {@link JSONParser} */ public JSONParser ofParser(final JSONTokener tokener){ - return JSONParser.of(tokener, this.config).setPredicate(this.predicate); + return JSONParser.of(tokener, this); } /** diff --git a/hutool-json/src/main/java/org/dromara/hutool/json/JSONPrimitive.java b/hutool-json/src/main/java/org/dromara/hutool/json/JSONPrimitive.java index d16775503..79ebe6377 100644 --- a/hutool-json/src/main/java/org/dromara/hutool/json/JSONPrimitive.java +++ b/hutool-json/src/main/java/org/dromara/hutool/json/JSONPrimitive.java @@ -201,6 +201,11 @@ public class JSONPrimitive implements Wrapper, JSON { } } + @Override + public String toString() { + return toJSONString(0); + } + /** * 写出数字,根据{@link JSONConfig#isStripTrailingZeros()} 配置不同,写出不同数字
* 主要针对Double型是否去掉小数点后多余的0
diff --git a/hutool-json/src/main/java/org/dromara/hutool/json/engine/HutoolJSONEngine.java b/hutool-json/src/main/java/org/dromara/hutool/json/engine/HutoolJSONEngine.java index 62375e968..4ccff81d1 100644 --- a/hutool-json/src/main/java/org/dromara/hutool/json/engine/HutoolJSONEngine.java +++ b/hutool-json/src/main/java/org/dromara/hutool/json/engine/HutoolJSONEngine.java @@ -16,10 +16,10 @@ package org.dromara.hutool.json.engine; +import org.dromara.hutool.core.util.ObjUtil; import org.dromara.hutool.json.JSON; import org.dromara.hutool.json.JSONConfig; import org.dromara.hutool.json.JSONFactory; -import org.dromara.hutool.json.JSONUtil; import java.io.Reader; import java.io.Writer; @@ -39,7 +39,8 @@ public class HutoolJSONEngine extends AbstractJSONEngine { public void serialize(final Object bean, final Writer writer) { initEngine(); final JSON json = jsonFactory.parse(bean); - json.write(jsonFactory.ofWriter(writer, this.config.isPrettyPrint())); + json.write(jsonFactory.ofWriter(writer, + ObjUtil.defaultIfNull(this.config, JSONEngineConfig::isPrettyPrint, false))); } @Override diff --git a/hutool-json/src/main/java/org/dromara/hutool/json/reader/JSONParser.java b/hutool-json/src/main/java/org/dromara/hutool/json/reader/JSONParser.java index c6dd869d9..b014d2cc0 100644 --- a/hutool-json/src/main/java/org/dromara/hutool/json/reader/JSONParser.java +++ b/hutool-json/src/main/java/org/dromara/hutool/json/reader/JSONParser.java @@ -40,33 +40,25 @@ public class JSONParser { * 创建JSONParser * * @param tokener {@link JSONTokener} - * @param config JSON配置 + * @param factory JSON工厂 * @return JSONParser */ - public static JSONParser of(final JSONTokener tokener, final JSONConfig config) { - return new JSONParser(tokener, config); + public static JSONParser of(final JSONTokener tokener, final JSONFactory factory) { + return new JSONParser(tokener, factory); } - /** - * JSON配置 - */ - private final JSONConfig config; private final JSONTokener tokener; - /** - * 过滤器,用于过滤或修改键值对,返回null表示忽略此键值对,返回非null表示修改后返回
- * entry中,key在JSONObject中为name,在JSONArray中为index - */ - private Predicate> predicate; + private final JSONFactory factory; /** * 构造 * * @param tokener {@link JSONTokener} - * @param config JSON配置 + * @param factory JSON工厂 */ - public JSONParser(final JSONTokener tokener, final JSONConfig config) { + public JSONParser(final JSONTokener tokener, final JSONFactory factory) { this.tokener = tokener; - this.config = config; + this.factory = factory; } /** @@ -78,17 +70,6 @@ public class JSONParser { return this.tokener; } - /** - * 设置过滤器,用于过滤或修改键值对,返回null表示忽略此键值对,返回非null表示修改后返回 - * - * @param predicate 过滤器,用于过滤或修改键值对,返回null表示忽略此键值对,返回非null表示修改后返回 - * @return this - */ - public JSONParser setPredicate(final Predicate> predicate) { - this.predicate = predicate; - return this; - } - /** * 获取下一个值,可以是: *
@@ -116,7 +97,7 @@ public class JSONParser {
 	 * @param json JSON对象或数组,用于存储解析结果
 	 */
 	public void parseTo(final JSON json) {
-		if(null == json){
+		if (null == json) {
 			return;
 		}
 		switch (tokener.nextClean()) {
@@ -146,12 +127,12 @@ public class JSONParser {
 		final JSON result;
 		switch (firstChar) {
 			case CharUtil.DELIM_START:
-				final JSONObject jsonObject = new JSONObject(config);
+				final JSONObject jsonObject = factory.ofObj();
 				nextTo(jsonObject);
 				result = jsonObject;
 				break;
 			case CharUtil.BRACKET_START:
-				final JSONArray jsonArray = new JSONArray(config);
+				final JSONArray jsonArray = factory.ofArray();
 				nextTo(jsonArray);
 				result = jsonArray;
 				break;
@@ -187,6 +168,7 @@ public class JSONParser {
 			// 过滤并设置键值对
 			final JSON value = nextJSON(tokener.nextClean());
 			// 添加前置过滤,通过MutablePair实现过滤、修改键值对等
+			final Predicate> predicate = factory.getPredicate();
 			if (null != predicate) {
 				final MutableEntry entry = new MutableEntry<>(key, value);
 				if (predicate.test(entry)) {
@@ -194,7 +176,7 @@ public class JSONParser {
 					key = (String) entry.getKey();
 					jsonObject.set(key, entry.getValue());
 				}
-			}else {
+			} else {
 				jsonObject.set(key, value);
 			}
 
@@ -233,6 +215,7 @@ public class JSONParser {
 			} else {
 				// ,value or value
 				JSON value = nextJSON(CharUtil.COMMA == c ? tokener.nextClean() : c);
+				final Predicate> predicate = factory.getPredicate();
 				if (null != predicate) {
 					// 使用过滤器
 					final MutableEntry entry = MutableEntry.of(jsonArray.size(), value);
@@ -264,11 +247,72 @@ public class JSONParser {
 			case CharUtil.DOUBLE_QUOTES:
 			case CharUtil.SINGLE_QUOTE:
 				// 引号包围,表示字符串值
-				return new JSONPrimitive(tokener.nextWrapString(firstChar), config);
+				return factory.ofPrimitive(tokener.nextWrapString(firstChar));
+			case 't':
+			case 'T':
+				checkTrue(tokener.next(3));
+				return factory.ofPrimitive(true);
+			case 'f':
+			case 'F':
+				checkFalse(tokener.next(4));
+				return factory.ofPrimitive(false);
+			case 'n':
+			case 'N':
+				checkNull(tokener.next(3));
+				return null;
 			default:
-				final Object value = InternalJSONUtil.parseValueFromString(tokener.nextUnwrapString(firstChar));
-				// 非引号包围,可能为boolean、数字、null等
-				return null == value ? null : new JSONPrimitive(value, config);
+				final Object value = InternalJSONUtil.parseNumberOrString(tokener.nextUnwrapString(firstChar));
+				// 非引号包围,可能为数字、null等
+				return null == value ? null : factory.ofPrimitive(value);
 		}
 	}
+
+	/**
+	 * 检查是否为true的rue部分
+	 *
+	 * @param next 值
+	 */
+	private void checkTrue(final char[] next) {
+		if ((next[0] == 'r' || next[0] == 'R') &&
+			(next[1] == 'u' || next[1] == 'U') &&
+			(next[2] == 'e' || next[2] == 'E')
+		) {
+			return;
+		}
+
+		throw tokener.syntaxError("Expected true but : t" + String.valueOf(next));
+	}
+
+	/**
+	 * 检查是否为false的alse部分
+	 *
+	 * @param next 值
+	 */
+	private void checkFalse(final char[] next) {
+		if ((next[0] == 'a' || next[0] == 'A') &&
+			(next[1] == 'l' || next[1] == 'L') &&
+			(next[2] == 's' || next[2] == 'S') &&
+			(next[3] == 'e' || next[3] == 'E')
+		) {
+			return;
+		}
+
+		throw tokener.syntaxError("Expected false but : f" + String.valueOf(next));
+	}
+
+	/**
+	 * 检查是否为null的ull部分
+	 *
+	 * @param next 值
+	 */
+	private void checkNull(final char[] next) {
+		if ((next[0] == 'u' || next[0] == 'U') &&
+			(next[1] == 'l' || next[1] == 'L') &&
+			(next[2] == 'l' || next[2] == 'L')
+		) {
+			return;
+		}
+
+		throw tokener.syntaxError("Expected null but : n" + String.valueOf(next));
+	}
 }
diff --git a/hutool-json/src/main/java/org/dromara/hutool/json/serializer/JSONContext.java b/hutool-json/src/main/java/org/dromara/hutool/json/serializer/JSONContext.java
index cfac420fa..e182f6f65 100644
--- a/hutool-json/src/main/java/org/dromara/hutool/json/serializer/JSONContext.java
+++ b/hutool-json/src/main/java/org/dromara/hutool/json/serializer/JSONContext.java
@@ -16,7 +16,6 @@
 
 package org.dromara.hutool.json.serializer;
 
-import org.dromara.hutool.core.util.ObjUtil;
 import org.dromara.hutool.json.*;
 
 /**
@@ -35,13 +34,20 @@ public interface JSONContext {
 	 */
 	JSON getContextJson();
 
+	/**
+	 * 获取JSON工厂
+	 *
+	 * @return JSON工厂
+	 */
+	JSONFactory getFactory();
+
 	/**
 	 * 获取JSON配置
 	 *
 	 * @return JSON配置
 	 */
 	default JSONConfig config() {
-		return ObjUtil.apply(getContextJson(), JSON::config);
+		return getFactory().getConfig();
 	}
 
 	/**
@@ -55,7 +61,7 @@ public interface JSONContext {
 			return (JSONObject) contextJson;
 		}
 
-		return JSONUtil.ofObj(config());
+		return getFactory().ofObj();
 	}
 
 	/**
@@ -68,7 +74,7 @@ public interface JSONContext {
 		if (contextJson instanceof JSONArray) {
 			return (JSONArray) contextJson;
 		}
-		return JSONUtil.ofArray(config());
+		return getFactory().ofArray();
 	}
 
 	/**
@@ -82,6 +88,6 @@ public interface JSONContext {
 		if (contextJson instanceof JSONPrimitive) {
 			return ((JSONPrimitive) contextJson).setValue(value);
 		}
-		return JSONUtil.ofPrimitive(value, config());
+		return getFactory().ofPrimitive(value);
 	}
 }
diff --git a/hutool-json/src/main/java/org/dromara/hutool/json/serializer/JSONMapper.java b/hutool-json/src/main/java/org/dromara/hutool/json/serializer/JSONMapper.java
index 0da332242..17f6a49ca 100644
--- a/hutool-json/src/main/java/org/dromara/hutool/json/serializer/JSONMapper.java
+++ b/hutool-json/src/main/java/org/dromara/hutool/json/serializer/JSONMapper.java
@@ -286,7 +286,7 @@ public class JSONMapper implements Serializable {
 
 		final JSON result;
 		try {
-			result = serializer.serialize(obj, new SimpleJSONContext(json, this.factory.getConfig()));
+			result = serializer.serialize(obj, new SimpleJSONContext(json, this.factory));
 		} catch (final Exception e) {
 			if (ignoreError) {
 				return null;
diff --git a/hutool-json/src/main/java/org/dromara/hutool/json/serializer/SimpleJSONContext.java b/hutool-json/src/main/java/org/dromara/hutool/json/serializer/SimpleJSONContext.java
index fa2e47d67..9fd1c47ff 100644
--- a/hutool-json/src/main/java/org/dromara/hutool/json/serializer/SimpleJSONContext.java
+++ b/hutool-json/src/main/java/org/dromara/hutool/json/serializer/SimpleJSONContext.java
@@ -16,9 +16,8 @@
 
 package org.dromara.hutool.json.serializer;
 
-import org.dromara.hutool.core.lang.Assert;
 import org.dromara.hutool.json.JSON;
-import org.dromara.hutool.json.JSONConfig;
+import org.dromara.hutool.json.JSONFactory;
 
 /**
  * 简单的JSON上下文,用于在JSON序列化时提供配置项
@@ -28,36 +27,27 @@ import org.dromara.hutool.json.JSONConfig;
  */
 public class SimpleJSONContext implements JSONContext {
 
-	private final JSON json;
-	private final JSONConfig config;
+	private final JSON contextJson;
+	private final JSONFactory factory;
 
 	/**
 	 * 构造
 	 *
-	 * @param json JSON对象
+	 * @param contextJson   JSON对象
+	 * @param factory 配置项
 	 */
-	public SimpleJSONContext(final JSON json) {
-		this(Assert.notNull(json), json.config());
-	}
-
-	/**
-	 * 构造
-	 *
-	 * @param json   JSON对象
-	 * @param config 配置项
-	 */
-	public SimpleJSONContext(final JSON json, final JSONConfig config) {
-		this.json = json;
-		this.config = config;
+	public SimpleJSONContext(final JSON contextJson, final JSONFactory factory) {
+		this.contextJson = contextJson;
+		this.factory = factory;
 	}
 
 	@Override
 	public JSON getContextJson() {
-		return this.json;
+		return this.contextJson;
 	}
 
 	@Override
-	public JSONConfig config() {
-		return this.config;
+	public JSONFactory getFactory() {
+		return factory;
 	}
 }
diff --git a/hutool-json/src/main/java/org/dromara/hutool/json/serializer/impl/ArrayTypeAdapter.java b/hutool-json/src/main/java/org/dromara/hutool/json/serializer/impl/ArrayTypeAdapter.java
index de6fa5092..dd7c9afe5 100644
--- a/hutool-json/src/main/java/org/dromara/hutool/json/serializer/impl/ArrayTypeAdapter.java
+++ b/hutool-json/src/main/java/org/dromara/hutool/json/serializer/impl/ArrayTypeAdapter.java
@@ -20,8 +20,9 @@ import org.dromara.hutool.core.array.ArrayUtil;
 import org.dromara.hutool.core.collection.iter.ArrayIter;
 import org.dromara.hutool.core.io.IoUtil;
 import org.dromara.hutool.core.reflect.TypeUtil;
-import org.dromara.hutool.json.*;
-import org.dromara.hutool.json.reader.JSONParser;
+import org.dromara.hutool.json.JSON;
+import org.dromara.hutool.json.JSONArray;
+import org.dromara.hutool.json.JSONObject;
 import org.dromara.hutool.json.reader.JSONTokener;
 import org.dromara.hutool.json.serializer.JSONContext;
 import org.dromara.hutool.json.serializer.MatcherJSONDeserializer;
@@ -96,12 +97,11 @@ public class ArrayTypeAdapter implements MatcherJSONSerializer, MatcherJ
 	 * @return JSONArray
 	 */
 	private JSON serializeBytes(final byte[] bytes, final JSONContext context) {
-		final JSONConfig config = context.config();
 		if(ArrayUtil.isNotEmpty(bytes)){
 			switch (bytes[0]) {
 				case '{':
 				case '[':
-					return JSONParser.of(new JSONTokener(IoUtil.toStream(bytes)), config).parse();
+					return context.getFactory().ofParser(new JSONTokener(IoUtil.toStream(bytes))).parse();
 			}
 		}
 
diff --git a/hutool-json/src/main/java/org/dromara/hutool/json/serializer/impl/CharSequenceTypeAdapter.java b/hutool-json/src/main/java/org/dromara/hutool/json/serializer/impl/CharSequenceTypeAdapter.java
index c8a2a0d8d..9c2912ea7 100644
--- a/hutool-json/src/main/java/org/dromara/hutool/json/serializer/impl/CharSequenceTypeAdapter.java
+++ b/hutool-json/src/main/java/org/dromara/hutool/json/serializer/impl/CharSequenceTypeAdapter.java
@@ -18,8 +18,9 @@ package org.dromara.hutool.json.serializer.impl;
 
 import org.dromara.hutool.core.reflect.TypeUtil;
 import org.dromara.hutool.core.text.StrUtil;
-import org.dromara.hutool.json.*;
-import org.dromara.hutool.json.reader.JSONParser;
+import org.dromara.hutool.json.JSON;
+import org.dromara.hutool.json.JSONObject;
+import org.dromara.hutool.json.JSONPrimitive;
 import org.dromara.hutool.json.reader.JSONTokener;
 import org.dromara.hutool.json.serializer.JSONContext;
 import org.dromara.hutool.json.serializer.MatcherJSONDeserializer;
@@ -62,7 +63,7 @@ public class CharSequenceTypeAdapter implements MatcherJSONSerializer {
 
 	@Override
 	public JSON serialize(final Resource bean, final JSONContext context) {
-		return mapFromTokener(new JSONTokener(bean.getStream()), context.config());
+		return context.getFactory().ofParser(new JSONTokener(bean.getStream())).parse();
 	}
 
 	/**
@@ -53,7 +53,7 @@ public class ResourceSerializer implements MatcherJSONSerializer {
 	 * @param tokener {@link JSONTokener}
 	 * @return JSON
 	 */
-	private JSON mapFromTokener(final JSONTokener tokener, final JSONConfig config) {
-		return JSONParser.of(tokener, config).setPredicate(null).parse();
+	private JSON mapFromTokener(final JSONTokener tokener, final JSONFactory factory) {
+		return JSONParser.of(tokener, factory).parse();
 	}
 }
diff --git a/hutool-json/src/main/java/org/dromara/hutool/json/serializer/impl/TokenerSerializer.java b/hutool-json/src/main/java/org/dromara/hutool/json/serializer/impl/TokenerSerializer.java
index a95ac1854..499acdf5f 100644
--- a/hutool-json/src/main/java/org/dromara/hutool/json/serializer/impl/TokenerSerializer.java
+++ b/hutool-json/src/main/java/org/dromara/hutool/json/serializer/impl/TokenerSerializer.java
@@ -17,7 +17,7 @@
 package org.dromara.hutool.json.serializer.impl;
 
 import org.dromara.hutool.json.JSON;
-import org.dromara.hutool.json.JSONConfig;
+import org.dromara.hutool.json.JSONFactory;
 import org.dromara.hutool.json.reader.JSONParser;
 import org.dromara.hutool.json.reader.JSONTokener;
 import org.dromara.hutool.json.serializer.JSONContext;
@@ -49,13 +49,13 @@ public class TokenerSerializer implements MatcherJSONSerializer {
 	public JSON serialize(final Object bean, final JSONContext context) {
 		// 读取JSON流
 		if (bean instanceof JSONTokener) {
-			return mapFromTokener((JSONTokener) bean, context.config());
+			return mapFromTokener((JSONTokener) bean, context.getFactory());
 		} else if (bean instanceof JSONParser) {
 			return ((JSONParser) bean).parse();
 		} else if (bean instanceof Reader) {
-			return mapFromTokener(new JSONTokener((Reader) bean), context.config());
+			return mapFromTokener(new JSONTokener((Reader) bean), context.getFactory());
 		} else if (bean instanceof InputStream) {
-			return mapFromTokener(new JSONTokener((InputStream) bean), context.config());
+			return mapFromTokener(new JSONTokener((InputStream) bean), context.getFactory());
 		}
 
 		throw new IllegalArgumentException("Unsupported source: " + bean);
@@ -67,7 +67,7 @@ public class TokenerSerializer implements MatcherJSONSerializer {
 	 * @param tokener {@link JSONTokener}
 	 * @return JSON
 	 */
-	private JSON mapFromTokener(final JSONTokener tokener, final JSONConfig config) {
-		return JSONParser.of(tokener, config).setPredicate(null).parse();
+	private JSON mapFromTokener(final JSONTokener tokener, final JSONFactory factory) {
+		return factory.ofParser(tokener).parse();
 	}
 }
diff --git a/hutool-json/src/test/java/org/dromara/hutool/json/reader/JSONParserTest.java b/hutool-json/src/test/java/org/dromara/hutool/json/reader/JSONParserTest.java
index f74d80a2e..43befaf73 100644
--- a/hutool-json/src/test/java/org/dromara/hutool/json/reader/JSONParserTest.java
+++ b/hutool-json/src/test/java/org/dromara/hutool/json/reader/JSONParserTest.java
@@ -24,7 +24,7 @@ public class JSONParserTest {
 	@Test
 	void parseTest() {
 		final String jsonStr = " {\"a\": 1} ";
-		final JSONParser jsonParser = JSONParser.of(new JSONTokener(jsonStr), JSONConfig.of());
+		final JSONParser jsonParser = JSONParser.of(new JSONTokener(jsonStr), JSONFactory.getInstance());
 		final JSON parse = jsonParser.parse();
 		Assertions.assertEquals("{\"a\":1}", parse.toString());
 	}
@@ -34,14 +34,14 @@ public class JSONParserTest {
 		final String jsonStr = "{\"a\": 1}";
 
 		final JSONObject jsonObject = JSONUtil.ofObj();
-		JSONParser.of(new JSONTokener(jsonStr), JSONConfig.of()).parseTo(jsonObject);
+		JSONParser.of(new JSONTokener(jsonStr), JSONFactory.getInstance()).parseTo(jsonObject);
 		Assertions.assertEquals("{\"a\":1}", jsonObject.toString());
 	}
 
 	@Test
 	void parseToArrayTest() {
 		final String jsonStr = "[{},2,3]";
-		final JSONParser jsonParser = JSONParser.of(new JSONTokener(jsonStr), JSONConfig.of());
+		final JSONParser jsonParser = JSONParser.of(new JSONTokener(jsonStr), JSONFactory.getInstance());
 		final JSONArray jsonArray = new JSONArray();
 		jsonParser.parseTo(jsonArray);