This commit is contained in:
Looly
2024-09-29 18:15:20 +08:00
parent 04b95fcb88
commit 9dfcac028e
5 changed files with 74 additions and 40 deletions

View File

@@ -188,6 +188,7 @@ public class IdUtilTest {
} }
@RepeatedTest(10) @RepeatedTest(10)
@Disabled
public void testUUIDv7Uniqueness() { public void testUUIDv7Uniqueness() {
final Set<org.dromara.hutool.core.data.id.UUID> uuids = new HashSet<>(); final Set<org.dromara.hutool.core.data.id.UUID> uuids = new HashSet<>();

View File

@@ -18,10 +18,8 @@ package org.dromara.hutool.json;
import org.dromara.hutool.core.lang.Assert; import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.lang.wrapper.Wrapper; 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.core.reflect.ClassUtil;
import org.dromara.hutool.json.writer.JSONWriter; import org.dromara.hutool.json.writer.JSONWriter;
import org.dromara.hutool.json.writer.NumberWriteMode;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.BigInteger; import java.math.BigInteger;
@@ -40,11 +38,6 @@ import java.math.BigInteger;
public class JSONPrimitive implements Wrapper<Object>, JSON { public class JSONPrimitive implements Wrapper<Object>, JSON {
private static final long serialVersionUID = -2026215279191790345L; private static final long serialVersionUID = -2026215279191790345L;
/**
* JS中表示的数字最大值
*/
private static final long JS_MAX_NUMBER = 9007199254740992L;
/** /**
* 判断给定对象是否可以转为JSONPrimitive类型 * 判断给定对象是否可以转为JSONPrimitive类型
* *
@@ -199,7 +192,7 @@ public class JSONPrimitive implements Wrapper<Object>, JSON {
writer.writeRaw(value.toString()); writer.writeRaw(value.toString());
} else if (value instanceof Number){ } else if (value instanceof Number){
// Number // Number
writeNumber(writer, (Number) value); writer.writeNumber((Number) value);
} else{ } else{
// 默认包装字符串 // 默认包装字符串
writer.writeQuoteStrValue(value.toString()); writer.writeQuoteStrValue(value.toString());
@@ -210,36 +203,4 @@ public class JSONPrimitive implements Wrapper<Object>, JSON {
public String toString() { public String toString() {
return toJSONString(0); return toJSONString(0);
} }
/**
* 写出数字,根据{@link JSONConfig#isStripTrailingZeros()} 配置不同,写出不同数字<br>
* 主要针对Double型是否去掉小数点后多余的0<br>
* 此方法输出的值不包装引号。
*
* @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;
}
}
} }

View File

@@ -18,18 +18,22 @@ package org.dromara.hutool.json.writer;
import org.dromara.hutool.core.io.IORuntimeException; import org.dromara.hutool.core.io.IORuntimeException;
import org.dromara.hutool.core.lang.mutable.MutableEntry; 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.CharUtil;
import org.dromara.hutool.core.text.StrUtil; import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.util.ObjUtil; import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.json.InternalJSONUtil; import org.dromara.hutool.json.InternalJSONUtil;
import org.dromara.hutool.json.JSON; import org.dromara.hutool.json.JSON;
import org.dromara.hutool.json.JSONConfig; import org.dromara.hutool.json.JSONConfig;
import org.dromara.hutool.json.JSONException;
import java.io.Closeable; import java.io.Closeable;
import java.io.Flushable; import java.io.Flushable;
import java.io.IOException; import java.io.IOException;
import java.io.Writer; import java.io.Writer;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.regex.Pattern;
/** /**
* JSON数据写出器<br> * JSON数据写出器<br>
@@ -74,6 +78,14 @@ public class JSONWriter implements Appendable, Flushable, Closeable {
return new JSONWriter(appendable, indentFactor, indent, config, predicate); 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 * Writer
*/ */
@@ -299,6 +311,42 @@ public class JSONWriter implements Appendable, Flushable, Closeable {
return this; return this;
} }
/**
* 写出数字,根据{@link JSONConfig#isStripTrailingZeros()} 配置不同,写出不同数字<br>
* 主要针对Double型是否去掉小数点后多余的0<br>
* 此方法输出的值不包装引号。
*
* @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 @Override
public JSONWriter append(final char c) throws IORuntimeException { public JSONWriter append(final char c) throws IORuntimeException {
try { try {

View File

@@ -16,6 +16,11 @@
package org.dromara.hutool.json.engine; 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.dromara.hutool.core.text.StrUtil;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -36,4 +41,19 @@ public class FastJSONTest {
" \"gender\":true\n" + " \"gender\":true\n" +
"}", jsonString); "}", 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();
}
} }

View File

@@ -5,6 +5,7 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import org.dromara.hutool.json.JSONObject; import org.dromara.hutool.json.JSONObject;
import org.dromara.hutool.json.JSONUtil; import org.dromara.hutool.json.JSONUtil;
import org.junit.jupiter.api.Assertions;
import org.openjdk.jmh.annotations.*; import org.openjdk.jmh.annotations.*;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@@ -34,15 +35,18 @@ public class JsonToStringJmh {
@Benchmark @Benchmark
public void gsonJmh() { public void gsonJmh() {
final String jsonStr = gson.toString(); final String jsonStr = gson.toString();
Assertions.assertNotNull(jsonStr);
} }
@Benchmark @Benchmark
public void hutoolJmh() { public void hutoolJmh() {
final String jsonStr = hutoolJSON.toString(); final String jsonStr = hutoolJSON.toString();
Assertions.assertNotNull(jsonStr);
} }
@Benchmark @Benchmark
public void fastJSONJmh() { public void fastJSONJmh() {
final String jsonStr = fastJSON.toString(); final String jsonStr = fastJSON.toString();
Assertions.assertNotNull(jsonStr);
} }
} }