From 463a8308e09f73fefb0bf99ba8744f32b085d759 Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 2 Oct 2024 14:57:15 +0800 Subject: [PATCH] add methods --- .../org/dromara/hutool/json/JSONArray.java | 66 ++++++++++++++++- .../org/dromara/hutool/json/JSONObject.java | 67 ++++++++++++++++++ .../dromara/hutool/json/JSONArrayTest.java | 2 +- .../org/dromara/hutool/json/JSONNullTest.java | 8 +-- .../dromara/hutool/json/JSONObjectTest.java | 2 +- .../dromara/hutool/json/jmh/JsonAddJmh.java | 70 +++++++++++++++++++ .../json/serializer/JSONMapperTest.java | 39 +++++++++++ 7 files changed, 245 insertions(+), 9 deletions(-) create mode 100644 hutool-json/src/test/java/org/dromara/hutool/json/jmh/JsonAddJmh.java create mode 100644 hutool-json/src/test/java/org/dromara/hutool/json/serializer/JSONMapperTest.java diff --git a/hutool-json/src/main/java/org/dromara/hutool/json/JSONArray.java b/hutool-json/src/main/java/org/dromara/hutool/json/JSONArray.java index 33f7d8013..397f340b7 100644 --- a/hutool-json/src/main/java/org/dromara/hutool/json/JSONArray.java +++ b/hutool-json/src/main/java/org/dromara/hutool/json/JSONArray.java @@ -112,11 +112,69 @@ public class JSONArray extends ListWrapper implements JSON, JSONGetter * 加入元素,数组长度+1,等同于 {@link JSONArray#add(Object)} * - * @param value 值,可以是: Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the JSONNull.NULL。 + * @param value Number值 + * @return this. + */ + public JSONArray addValue(final Boolean value) { + // add时,不解析字符串,而是作为JSONPrimitive对待 + this.add(this.factory.ofPrimitive(value)); + return this; + } + + /** + * 加入元素,数组长度+1,等同于 {@link JSONArray#add(Object)} + * + * @param value Number值 + * @return this. + */ + public JSONArray addValue(final Number value) { + // add时,不解析字符串,而是作为JSONPrimitive对待 + this.add(this.factory.ofPrimitive(value)); + return this; + } + + /** + * 加入元素,数组长度+1,等同于 {@link JSONArray#add(Object)} + * + * @param value Character值 + * @return this. + */ + public JSONArray addValue(final Character value) { + // add时,不解析字符串,而是作为JSONPrimitive对待 + this.add(this.factory.ofPrimitive(value)); + return this; + } + + /** + * 加入元素,数组长度+1,等同于 {@link JSONArray#add(Object)} + * + * @param value String值 + * @return this. + */ + public JSONArray addValue(final String value) { + // add时,不解析字符串,而是作为JSONPrimitive对待 + this.add(this.factory.ofPrimitive(value)); + return this; + } + + /** + * 加入元素,数组长度+1,等同于 {@link JSONArray#add(Object)} + * + * @param value 值,可以是: Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the {@code null}。 * @return this. */ public JSONArray addValue(final Object value) { @@ -124,6 +182,7 @@ public class JSONArray extends ListWrapper implements JSON, JSONGetter implements JSON, JSONGetter implements JSON, JSONGetter implements JSON, JSONGe return this; } + /** + * 设置设置{@code null}值。在忽略null模式下移除对应键值对。 + * + * @param key 键 + * @return this. + */ + public JSONObject putNull(final String key){ + this.put(key, null); + return this; + } + + /** + * 设置键值对到JSONObject中,在忽略null模式下,如果值为{@code null},将此键移除 + * + * @param key 键 + * @param value Boolean类型对象 + * @return this. + * @throws JSONException 值是无穷数字抛出此异常 + */ + public JSONObject putValue(final String key, final Boolean value) throws JSONException { + this.put(key, factory.ofPrimitive(value)); + return this; + } + + /** + * 设置键值对到JSONObject中,在忽略null模式下,如果值为{@code null},将此键移除 + * + * @param key 键 + * @param value Number类型对象 + * @return this. + * @throws JSONException 值是无穷数字抛出此异常 + */ + public JSONObject putValue(final String key, final Number value) throws JSONException { + this.put(key, factory.ofPrimitive(value)); + return this; + } + + /** + * 设置键值对到JSONObject中,在忽略null模式下,如果值为{@code null},将此键移除 + * + * @param key 键 + * @param value Character类型对象 + * @return this. + * @throws JSONException 值是无穷数字抛出此异常 + */ + public JSONObject putValue(final String key, final Character value) throws JSONException { + this.put(key, factory.ofPrimitive(value)); + return this; + } + + /** + * 设置键值对到JSONObject中,在忽略null模式下,如果值为{@code null},将此键移除 + * + * @param key 键 + * @param value String类型对象 + * @return this. + * @throws JSONException 值是无穷数字抛出此异常 + */ + public JSONObject putValue(final String key, final String value) throws JSONException { + // put时,不解析字符串,而是作为JSONPrimitive对待 + this.put(key, factory.ofPrimitive(value)); + return this; + } + /** * 设置键值对到JSONObject中,在忽略null模式下,如果值为{@code null},将此键移除 * @@ -236,6 +300,9 @@ public class JSONObject extends MapWrapper implements JSON, JSONGe * @throws JSONException 值是无穷数字抛出此异常 */ public JSONObject putValue(final String key, final Object value) throws JSONException { + if(null == value){ + return putNull(key); + } // put时,如果value为字符串,不解析,而是作为JSONPrimitive对待 this.put(key, factory.getMapper().toJSON(value, false)); return this; diff --git a/hutool-json/src/test/java/org/dromara/hutool/json/JSONArrayTest.java b/hutool-json/src/test/java/org/dromara/hutool/json/JSONArrayTest.java index cd958d3cc..f7e498194 100644 --- a/hutool-json/src/test/java/org/dromara/hutool/json/JSONArrayTest.java +++ b/hutool-json/src/test/java/org/dromara/hutool/json/JSONArrayTest.java @@ -300,7 +300,7 @@ public class JSONArrayTest { @Test public void putNullTest() { final JSONArray array = JSONUtil.ofArray(JSONConfig.of().setIgnoreNullValue(false)); - array.addValue(null); + array.addNull(); assertEquals("[null]", array.toString()); } diff --git a/hutool-json/src/test/java/org/dromara/hutool/json/JSONNullTest.java b/hutool-json/src/test/java/org/dromara/hutool/json/JSONNullTest.java index 9ef51b3de..166ceb4de 100644 --- a/hutool-json/src/test/java/org/dromara/hutool/json/JSONNullTest.java +++ b/hutool-json/src/test/java/org/dromara/hutool/json/JSONNullTest.java @@ -51,22 +51,22 @@ public class JSONNullTest { @Test public void setNullTest(){ // 忽略null - String json1 = JSONUtil.ofObj().putValue("key1", null).toString(); + String json1 = JSONUtil.ofObj().putNull("key1").toString(); Assertions.assertEquals("{}", json1); // 不忽略null - json1 = JSONUtil.ofObj(JSONConfig.of().setIgnoreNullValue(false)).putValue("key1", null).toString(); + json1 = JSONUtil.ofObj(JSONConfig.of().setIgnoreNullValue(false)).putNull("key1").toString(); Assertions.assertEquals("{\"key1\":null}", json1); } @Test public void setNullOfJSONArrayTest(){ // 忽略null - String json1 = JSONUtil.ofArray().addValue(null).toString(); + String json1 = JSONUtil.ofArray().addNull().toString(); Assertions.assertEquals("[]", json1); // 不忽略null - json1 = JSONUtil.ofArray(JSONConfig.of().setIgnoreNullValue(false)).addValue(null).toString(); + json1 = JSONUtil.ofArray(JSONConfig.of().setIgnoreNullValue(false)).addNull().toString(); Assertions.assertEquals("[null]", json1); } } diff --git a/hutool-json/src/test/java/org/dromara/hutool/json/JSONObjectTest.java b/hutool-json/src/test/java/org/dromara/hutool/json/JSONObjectTest.java index 3d1c82411..4d913d723 100644 --- a/hutool-json/src/test/java/org/dromara/hutool/json/JSONObjectTest.java +++ b/hutool-json/src/test/java/org/dromara/hutool/json/JSONObjectTest.java @@ -730,7 +730,7 @@ public class JSONObjectTest { @Test public void nullToEmptyTest() { final JSONObject json1 = JSONUtil.ofObj(JSONConfig.of().setIgnoreNullValue(false)) - .putValue("a", null) + .putNull("a") .putValue("b", "value2"); final String s = json1.toJSONString(0, (pair) -> { diff --git a/hutool-json/src/test/java/org/dromara/hutool/json/jmh/JsonAddJmh.java b/hutool-json/src/test/java/org/dromara/hutool/json/jmh/JsonAddJmh.java new file mode 100644 index 000000000..d6c5854e6 --- /dev/null +++ b/hutool-json/src/test/java/org/dromara/hutool/json/jmh/JsonAddJmh.java @@ -0,0 +1,70 @@ +package org.dromara.hutool.json.jmh; + +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.google.gson.JsonArray; +import org.dromara.hutool.core.lang.Console; +import org.dromara.hutool.core.util.RandomUtil; +import org.dromara.hutool.json.JSONArray; +import org.openjdk.jmh.annotations.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * 测试JSON树结构转JSON字符串性能 + */ +@BenchmarkMode(Mode.AverageTime)//每次执行平均花费时间 +@Warmup(iterations = 1, time = 1) //预热5次调用 +@Measurement(iterations = 1, time = 1, timeUnit = TimeUnit.SECONDS) // 执行5此,每次1秒 +@Threads(1) //单线程 +@Fork(1) // +@OutputTimeUnit(TimeUnit.NANOSECONDS) // 单位:纳秒 +@State(Scope.Benchmark) // 共享域 +public class JsonAddJmh { + + List testData; + private JSONArray hutoolJSON; + private JsonArray gson; + private com.alibaba.fastjson2.JSONArray fastJSON; + private ArrayNode jackson; + + + @Setup + public void setup() { + Console.log("准备数据。。。"); + testData = new ArrayList<>(10); + for (int i = 0; i < 10; i++) { + testData.add(RandomUtil.randomString(20)); + } + + hutoolJSON = new JSONArray(); + gson = new JsonArray(); + fastJSON = new com.alibaba.fastjson2.JSONArray(); + jackson = JsonNodeFactory.instance.arrayNode(); + Console.log("数据完毕"); + } + + @Benchmark + public void gsonJmh() { + testData.forEach(gson::add); + } + + @Benchmark + public void hutoolJmh() { + testData.forEach(hutoolJSON::addValue); + //hutoolJSON.putAllObj(testData); + } + + @SuppressWarnings("UseBulkOperation") + @Benchmark + public void fastJSONJmh() { + testData.forEach(fastJSON::add); + } + + @Benchmark + public void jacksonJmh(){ + testData.forEach(jackson::add); + } +} diff --git a/hutool-json/src/test/java/org/dromara/hutool/json/serializer/JSONMapperTest.java b/hutool-json/src/test/java/org/dromara/hutool/json/serializer/JSONMapperTest.java new file mode 100644 index 000000000..693cd6352 --- /dev/null +++ b/hutool-json/src/test/java/org/dromara/hutool/json/serializer/JSONMapperTest.java @@ -0,0 +1,39 @@ +package org.dromara.hutool.json.serializer; + +import org.dromara.hutool.core.date.DateUtil; +import org.dromara.hutool.core.date.StopWatch; +import org.dromara.hutool.core.lang.Console; +import org.dromara.hutool.json.JSONFactory; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +public class JSONMapperTest { + + /** + * Mapper性能耗费较多 + */ + @Test + @Disabled + void toJSONTest() { + final JSONFactory factory = JSONFactory.getInstance(); + + final JSONMapper mapper = factory.getMapper(); + + final StopWatch stopWatch = DateUtil.createStopWatch(); + + final int count = 1000; + stopWatch.start("use mapper"); + for (int i = 0; i < count; i++) { + mapper.toJSON("qbw123", false); + } + stopWatch.stop(); + + stopWatch.start("use ofPrimitive"); + for (int i = 0; i < count; i++) { + factory.ofPrimitive("qbw123"); + } + stopWatch.stop(); + + Console.log(stopWatch.prettyPrint()); + } +}