diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/util/IdUtilTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/util/IdUtilTest.java index d93f7b6d1..c7cff8b65 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/util/IdUtilTest.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/util/IdUtilTest.java @@ -188,6 +188,7 @@ public class IdUtilTest { } @RepeatedTest(10) + @Disabled public void testUUIDv7Uniqueness() { final Set uuids = new HashSet<>(); 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 7a69062f5..80f0f4fb4 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 @@ -18,10 +18,8 @@ package org.dromara.hutool.json; import org.dromara.hutool.core.lang.Assert; import org.dromara.hutool.core.lang.wrapper.Wrapper; -import org.dromara.hutool.core.math.NumberUtil; import org.dromara.hutool.core.reflect.ClassUtil; import org.dromara.hutool.json.writer.JSONWriter; -import org.dromara.hutool.json.writer.NumberWriteMode; import java.math.BigDecimal; import java.math.BigInteger; @@ -40,11 +38,6 @@ import java.math.BigInteger; public class JSONPrimitive implements Wrapper, JSON { private static final long serialVersionUID = -2026215279191790345L; - /** - * JS中表示的数字最大值 - */ - private static final long JS_MAX_NUMBER = 9007199254740992L; - /** * 判断给定对象是否可以转为JSONPrimitive类型 * @@ -199,7 +192,7 @@ public class JSONPrimitive implements Wrapper, JSON { writer.writeRaw(value.toString()); } else if (value instanceof Number){ // Number - writeNumber(writer, (Number) value); + writer.writeNumber((Number) value); } else{ // 默认包装字符串 writer.writeQuoteStrValue(value.toString()); @@ -210,36 +203,4 @@ public class JSONPrimitive implements Wrapper, JSON { public String toString() { return toJSONString(0); } - - /** - * 写出数字,根据{@link JSONConfig#isStripTrailingZeros()} 配置不同,写出不同数字
- * 主要针对Double型是否去掉小数点后多余的0
- * 此方法输出的值不包装引号。 - * - * @param writer {@link JSONWriter} - * @param number 数字 - */ - private void writeNumber(final JSONWriter writer, final Number number) { - final JSONConfig config = writer.getConfig(); - // since 5.6.2可配置是否去除末尾多余0,例如如果为true,5.0返回5 - final boolean isStripTrailingZeros = (null == config) || config.isStripTrailingZeros(); - final String numberStr = NumberUtil.toStr(number, isStripTrailingZeros); - - final NumberWriteMode numberWriteMode = (null == config) ? NumberWriteMode.NORMAL : config.getNumberWriteMode(); - switch (numberWriteMode){ - case JS: - if(number.longValue() > JS_MAX_NUMBER){ - writer.writeQuoteStrValue(numberStr); - } else{ - writer.writeRaw(numberStr); - } - break; - case STRING: - writer.writeQuoteStrValue(numberStr); - break; - default: - writer.writeRaw(numberStr); - break; - } - } } diff --git a/hutool-json/src/main/java/org/dromara/hutool/json/writer/JSONWriter.java b/hutool-json/src/main/java/org/dromara/hutool/json/writer/JSONWriter.java index 8e460efe5..994a4aece 100644 --- a/hutool-json/src/main/java/org/dromara/hutool/json/writer/JSONWriter.java +++ b/hutool-json/src/main/java/org/dromara/hutool/json/writer/JSONWriter.java @@ -18,18 +18,22 @@ package org.dromara.hutool.json.writer; import org.dromara.hutool.core.io.IORuntimeException; import org.dromara.hutool.core.lang.mutable.MutableEntry; +import org.dromara.hutool.core.math.NumberUtil; +import org.dromara.hutool.core.regex.ReUtil; import org.dromara.hutool.core.text.CharUtil; import org.dromara.hutool.core.text.StrUtil; import org.dromara.hutool.core.util.ObjUtil; import org.dromara.hutool.json.InternalJSONUtil; import org.dromara.hutool.json.JSON; import org.dromara.hutool.json.JSONConfig; +import org.dromara.hutool.json.JSONException; import java.io.Closeable; import java.io.Flushable; import java.io.IOException; import java.io.Writer; import java.util.function.Predicate; +import java.util.regex.Pattern; /** * JSON数据写出器
@@ -74,6 +78,14 @@ public class JSONWriter implements Appendable, Flushable, Closeable { return new JSONWriter(appendable, indentFactor, indent, config, predicate); } + /** + * JS中表示的数字最大值 + */ + private static final long JS_MAX_NUMBER = 9007199254740992L; + // Syntax as defined by https://datatracker.ietf.org/doc/html/rfc8259#section-6 + private static final Pattern JSON_NUMBER_PATTERN = + Pattern.compile("-?(?:0|[1-9][0-9]*)(?:\\.[0-9]+)?(?:[eE][-+]?[0-9]+)?"); + /** * Writer */ @@ -299,6 +311,42 @@ public class JSONWriter implements Appendable, Flushable, Closeable { return this; } + /** + * 写出数字,根据{@link JSONConfig#isStripTrailingZeros()} 配置不同,写出不同数字
+ * 主要针对Double型是否去掉小数点后多余的0
+ * 此方法输出的值不包装引号。 + * + * @param number 数字 + * @return this + */ + public JSONWriter writeNumber(final Number number) { + // since 5.6.2可配置是否去除末尾多余0,例如如果为true,5.0返回5 + final boolean isStripTrailingZeros = (null == config) || config.isStripTrailingZeros(); + final String numberStr = NumberUtil.toStr(number, isStripTrailingZeros); + + // 检查有效性 + if(!ReUtil.isMatch(JSON_NUMBER_PATTERN, numberStr)){ + throw new JSONException("Invalid RFC8259 JSON format number: " + numberStr); + } + + final NumberWriteMode numberWriteMode = (null == config) ? NumberWriteMode.NORMAL : config.getNumberWriteMode(); + switch (numberWriteMode){ + case JS: + if(number.longValue() > JS_MAX_NUMBER){ + writeQuoteStrValue(numberStr); + } else{ + return writeRaw(numberStr); + } + break; + case STRING: + writeQuoteStrValue(numberStr); + break; + default: + return writeRaw(numberStr); + } + return this; + } + @Override public JSONWriter append(final char c) throws IORuntimeException { try { diff --git a/hutool-json/src/test/java/org/dromara/hutool/json/engine/FastJSONTest.java b/hutool-json/src/test/java/org/dromara/hutool/json/engine/FastJSONTest.java index a7001227e..d9bb87e8f 100644 --- a/hutool-json/src/test/java/org/dromara/hutool/json/engine/FastJSONTest.java +++ b/hutool-json/src/test/java/org/dromara/hutool/json/engine/FastJSONTest.java @@ -16,6 +16,11 @@ package org.dromara.hutool.json.engine; +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; +import com.alibaba.fastjson2.JSONWriter; +import com.alibaba.fastjson2.writer.ObjectWriter; +import org.dromara.hutool.core.lang.Console; import org.dromara.hutool.core.text.StrUtil; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -36,4 +41,19 @@ public class FastJSONTest { " \"gender\":true\n" + "}", jsonString); } + + @Test + void toStringTest() { + final String jsonStr = "{\"name\":\"张三\",\"age\":18,\"birthday\":\"2020-01-01\"}"; + final JSONObject jsonObject = JSON.parseObject(jsonStr); + final JSONWriter writer = JSONWriter.of(); + writer.setRootObject(jsonObject); + writer.write(jsonObject); + + final JSONWriter.Context context = writer.getContext(); + final ObjectWriter objectWriter = context.getObjectWriter(jsonObject.getClass()); + Console.log(objectWriter.getClass()); + + writer.close(); + } } diff --git a/hutool-json/src/test/java/org/dromara/hutool/json/jmh/JsonToStringJmh.java b/hutool-json/src/test/java/org/dromara/hutool/json/jmh/JsonToStringJmh.java index c32e73b2f..8fe971acb 100644 --- a/hutool-json/src/test/java/org/dromara/hutool/json/jmh/JsonToStringJmh.java +++ b/hutool-json/src/test/java/org/dromara/hutool/json/jmh/JsonToStringJmh.java @@ -5,6 +5,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonParser; import org.dromara.hutool.json.JSONObject; import org.dromara.hutool.json.JSONUtil; +import org.junit.jupiter.api.Assertions; import org.openjdk.jmh.annotations.*; import java.util.concurrent.TimeUnit; @@ -34,15 +35,18 @@ public class JsonToStringJmh { @Benchmark public void gsonJmh() { final String jsonStr = gson.toString(); + Assertions.assertNotNull(jsonStr); } @Benchmark public void hutoolJmh() { final String jsonStr = hutoolJSON.toString(); + Assertions.assertNotNull(jsonStr); } @Benchmark public void fastJSONJmh() { final String jsonStr = fastJSON.toString(); + Assertions.assertNotNull(jsonStr); } }