From 48231de90fb24eb6b82a26d4a63b18488a1a738b Mon Sep 17 00:00:00 2001 From: "shaojin.wensj" Date: Sun, 7 May 2023 15:12:32 +0800 Subject: [PATCH] speed up serialize & deserialize --- .../main/java/com/alibaba/fastjson2/JSON.java | 26 +++++++++ .../com/alibaba/fastjson2/JSONReader.java | 5 +- .../alibaba/fastjson2/JSONReaderUTF16.java | 6 ++ .../com/alibaba/fastjson2/JSONReaderUTF8.java | 6 ++ .../com/alibaba/fastjson2/JSONWriter.java | 32 +---------- .../alibaba/fastjson2/JSONWriterJSONB.java | 2 +- .../alibaba/fastjson2/JSONWriterPretty.java | 10 +++- .../alibaba/fastjson2/JSONWriterUTF16.java | 55 ++++++++++++++++++- .../com/alibaba/fastjson2/JSONWriterUTF8.java | 55 ++++++++++++++++++- .../java/com/alibaba/fastjson2/JSONTest.java | 9 +++ .../primitves/IntValueArrayField1Test.java | 16 ++++++ .../primitves/LongValueArrayField1Test.java | 17 ++++++ .../fastjson2/JSONWriterUTF16Vector.java | 2 +- .../fastjson2/JSONWriterUTF8Vector.java | 2 +- 14 files changed, 204 insertions(+), 39 deletions(-) diff --git a/core/src/main/java/com/alibaba/fastjson2/JSON.java b/core/src/main/java/com/alibaba/fastjson2/JSON.java index f797902454..0b06f6adfd 100644 --- a/core/src/main/java/com/alibaba/fastjson2/JSON.java +++ b/core/src/main/java/com/alibaba/fastjson2/JSON.java @@ -2715,6 +2715,32 @@ static byte[] toJSONBytes(Object object, String format, Filter[] filters, JSONWr } } + /** + * Serialize Java Object to JSON and write to {@link OutputStream} + * + * @param out {@link OutputStream} to be written + * @param object Java Object to be serialized into JSON + * @throws JSONException if an I/O error occurs. In particular, a {@link JSONException} may be thrown if the output stream has been closed + */ + static int writeTo(OutputStream out, Object object) { + try (JSONWriter writer = JSONWriter.ofUTF8()) { + if (object == null) { + writer.writeNull(); + } else { + writer.rootObject = object; + writer.path = JSONWriter.Path.ROOT; + + Class valueClass = object.getClass(); + ObjectWriter objectWriter = writer.getObjectWriter(valueClass, valueClass); + objectWriter.write(writer, object, null, null, 0); + } + + return writer.flushTo(out); + } catch (Exception e) { + throw new JSONException(e.getMessage(), e); + } + } + /** * Serialize Java Object to JSON and write to {@link OutputStream} with specified {@link JSONReader.Feature}s enabled * diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONReader.java b/core/src/main/java/com/alibaba/fastjson2/JSONReader.java index 789a334b49..46db6ead81 100644 --- a/core/src/main/java/com/alibaba/fastjson2/JSONReader.java +++ b/core/src/main/java/com/alibaba/fastjson2/JSONReader.java @@ -772,10 +772,7 @@ public BigInteger readBigInteger() { return getBigInteger(); } - public BigDecimal readBigDecimal() { - readNumber0(); - return getBigDecimal(); - } + public abstract BigDecimal readBigDecimal(); public abstract UUID readUUID(); diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF16.java b/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF16.java index eb3c58072a..f0e2c82a3d 100644 --- a/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF16.java +++ b/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF16.java @@ -8,6 +8,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.Reader; +import java.math.BigDecimal; import java.math.BigInteger; import java.time.*; import java.util.*; @@ -4623,6 +4624,11 @@ public final void readNull() { } } + public final BigDecimal readBigDecimal() { + readNumber0(); + return getBigDecimal(); + } + @Override public final UUID readUUID() { if (ch == 'n') { diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF8.java b/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF8.java index 63e5fe3595..4a1a66ad6d 100644 --- a/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF8.java +++ b/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF8.java @@ -5,6 +5,7 @@ import java.io.IOException; import java.io.InputStream; +import java.math.BigDecimal; import java.math.BigInteger; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; @@ -5105,6 +5106,11 @@ protected final LocalDateTime readLocalDateTimeX(int len) { return ldt; } + public final BigDecimal readBigDecimal() { + readNumber0(); + return getBigDecimal(); + } + @Override public final UUID readUUID() { if (ch == 'n') { diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONWriter.java b/core/src/main/java/com/alibaba/fastjson2/JSONWriter.java index e09170ca1e..3893c3a859 100644 --- a/core/src/main/java/com/alibaba/fastjson2/JSONWriter.java +++ b/core/src/main/java/com/alibaba/fastjson2/JSONWriter.java @@ -898,20 +898,7 @@ public void writeInt16(short value) { writeInt32(value); } - public void writeInt32(int[] value) { - if (value == null) { - writeNull(); - return; - } - startArray(); - for (int i = 0; i < value.length; i++) { - if (i != 0) { - writeComma(); - } - writeInt32(value[i]); - } - endArray(); - } + public abstract void writeInt32(int[] value); public abstract void writeInt32(int value); @@ -921,20 +908,7 @@ public void writeMillis(long i) { writeInt64(i); } - public void writeInt64(long[] value) { - if (value == null) { - writeNull(); - return; - } - startArray(); - for (int i = 0; i < value.length; i++) { - if (i != 0) { - writeComma(); - } - writeInt64(value[i]); - } - endArray(); - } + public abstract void writeInt64(long[] value); public abstract void writeFloat(float value); @@ -1208,7 +1182,7 @@ public final void writeString(Reader reader) { } public abstract void writeString(String str); - public abstract void writeStringLatin1(byte[] value); + protected abstract void writeStringLatin1(byte[] value); public void writeString(List list) { startArray(); diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONWriterJSONB.java b/core/src/main/java/com/alibaba/fastjson2/JSONWriterJSONB.java index 8dc0f1d0a5..f77e1fdc09 100644 --- a/core/src/main/java/com/alibaba/fastjson2/JSONWriterJSONB.java +++ b/core/src/main/java/com/alibaba/fastjson2/JSONWriterJSONB.java @@ -214,7 +214,7 @@ public void writeString(char[] chars, int off, int len, boolean quote) { writeString(new String(chars, off, len)); } - public void writeStringLatin1(final byte[] str) { + protected void writeStringLatin1(final byte[] str) { if (str == null) { writeStringNull(); return; diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONWriterPretty.java b/core/src/main/java/com/alibaba/fastjson2/JSONWriterPretty.java index 661c06949c..6c7712d2bb 100644 --- a/core/src/main/java/com/alibaba/fastjson2/JSONWriterPretty.java +++ b/core/src/main/java/com/alibaba/fastjson2/JSONWriterPretty.java @@ -35,6 +35,10 @@ public void close() { jsonWriter.close(); } + public void writeInt32(int[] value) { + jsonWriter.writeInt32(value); + } + @Override public void writeInt32(int value) { jsonWriter.writeInt32(value); @@ -45,6 +49,10 @@ public void writeInt64(long i) { jsonWriter.writeInt64(i); } + public void writeInt64(long[] value) { + jsonWriter.writeInt64(value); + } + @Override public void writeFloat(float value) { jsonWriter.writeFloat(value); @@ -76,7 +84,7 @@ public void writeString(String str) { } @Override - public void writeStringLatin1(byte[] str) { + protected void writeStringLatin1(byte[] str) { jsonWriter.writeStringLatin1(str); } diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16.java b/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16.java index 48d290ac56..f191935077 100644 --- a/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16.java +++ b/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16.java @@ -146,7 +146,7 @@ public final void writeString(List list) { chars[off++] = ']'; } - public void writeStringLatin1(byte[] value) { + protected void writeStringLatin1(byte[] value) { if (value == null) { writeStringNull(); return; @@ -1255,6 +1255,33 @@ final void ensureCapacity(int minCapacity) { } } + public final void writeInt32(int[] value) { + if (value == null) { + writeNull(); + return; + } + + if (off == chars.length) { + ensureCapacity(off + 1); + } + chars[off++] = '['; + + for (int i = 0; i < value.length; i++) { + if (i != 0) { + if (off == chars.length) { + ensureCapacity(off + 1); + } + chars[off++] = ','; + } + writeInt32(value[i]); + } + + if (off == chars.length) { + ensureCapacity(off + 1); + } + chars[off++] = ']'; + } + @Override public final void writeInt32(int i) { boolean writeAsString = (context.features & Feature.WriteNonStringValueAsString.mask) != 0; @@ -1343,6 +1370,32 @@ public final void writeInt32(int i) { } } + public final void writeInt64(long[] value) { + if (value == null) { + writeNull(); + return; + } + + if (off == chars.length) { + ensureCapacity(off + 1); + } + chars[off++] = '['; + + for (int i = 0; i < value.length; i++) { + if (i != 0) { + if (off == chars.length) { + ensureCapacity(off + 1); + } + chars[off++] = ','; + } + writeInt64(value[i]); + } + if (off == chars.length) { + ensureCapacity(off + 1); + } + chars[off++] = (byte) ']'; + } + @Override public final void writeInt64(long i) { boolean writeAsString = (context.features & (WriteNonStringValueAsString.mask | WriteLongAsString.mask)) != 0 diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF8.java b/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF8.java index 8326bc9e44..3ad9f556fe 100644 --- a/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF8.java +++ b/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF8.java @@ -359,7 +359,7 @@ public void writeString(String str) { bytes[off++] = (byte) quote; } - public void writeStringLatin1(byte[] value) { + protected void writeStringLatin1(byte[] value) { if (value == null) { writeStringNull(); return; @@ -1548,6 +1548,33 @@ final void ensureCapacity(int minCapacity) { } } + public final void writeInt32(int[] value) { + if (value == null) { + writeNull(); + return; + } + + if (off == bytes.length) { + ensureCapacity(off + 1); + } + bytes[off++] = (byte) '['; + + for (int i = 0; i < value.length; i++) { + if (i != 0) { + if (off == bytes.length) { + ensureCapacity(off + 1); + } + bytes[off++] = (byte) ','; + } + writeInt32(value[i]); + } + + if (off == bytes.length) { + ensureCapacity(off + 1); + } + bytes[off++] = (byte) ']'; + } + @Override public final void writeInt32(int i) { boolean writeAsString = (context.features & Feature.WriteNonStringValueAsString.mask) != 0; @@ -1636,6 +1663,32 @@ public final void writeInt32(int i) { } } + public final void writeInt64(long[] value) { + if (value == null) { + writeNull(); + return; + } + + if (off == bytes.length) { + ensureCapacity(off + 1); + } + bytes[off++] = (byte) '['; + + for (int i = 0; i < value.length; i++) { + if (i != 0) { + if (off == bytes.length) { + ensureCapacity(off + 1); + } + bytes[off++] = (byte) ','; + } + writeInt64(value[i]); + } + if (off == bytes.length) { + ensureCapacity(off + 1); + } + bytes[off++] = (byte) ']'; + } + @Override public final void writeInt64(long i) { boolean writeAsString = (context.features & (WriteNonStringValueAsString.mask | WriteLongAsString.mask)) != 0 diff --git a/core/src/test/java/com/alibaba/fastjson2/JSONTest.java b/core/src/test/java/com/alibaba/fastjson2/JSONTest.java index b00036ce02..2439c71445 100644 --- a/core/src/test/java/com/alibaba/fastjson2/JSONTest.java +++ b/core/src/test/java/com/alibaba/fastjson2/JSONTest.java @@ -669,6 +669,13 @@ public void test_writeTo_0() { assertEquals("[1]", new String(out.toByteArray())); } + @Test + public void test_writeTo_0_f() { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + JSON.writeTo(out, Collections.singleton(1), JSONWriter.Feature.WriteNulls); + assertEquals("[1]", + new String(out.toByteArray())); + } @Test public void test_writeTo_1() { @@ -1020,6 +1027,8 @@ public void write(byte[] b, int off, int len) { }; assertThrows(JSONException.class, () -> JSON.writeTo(out, JSONObject.of("id", 123))); + assertThrows(JSONException.class, () -> + JSON.writeTo(out, JSONObject.of("id", 123), JSONWriter.Feature.PrettyFormat)); } { ByteArrayOutputStream out = new ByteArrayOutputStream(); diff --git a/core/src/test/java/com/alibaba/fastjson2/primitves/IntValueArrayField1Test.java b/core/src/test/java/com/alibaba/fastjson2/primitves/IntValueArrayField1Test.java index cda98b58f4..57d336d756 100644 --- a/core/src/test/java/com/alibaba/fastjson2/primitves/IntValueArrayField1Test.java +++ b/core/src/test/java/com/alibaba/fastjson2/primitves/IntValueArrayField1Test.java @@ -1,6 +1,8 @@ package com.alibaba.fastjson2.primitves; +import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONReader; +import com.alibaba.fastjson2.JSONWriter; import com.alibaba.fastjson2.TestUtils; import com.alibaba.fastjson2.reader.FieldReader; import com.alibaba.fastjson2.reader.ObjectReader; @@ -73,4 +75,18 @@ public void test_final_0() throws Exception { } } } + + @Test + public void test_write_0() throws Exception { + IntValueArrayField1 bean = new IntValueArrayField1(); + bean.values = new int[] {101, 102, 103}; + assertEquals("{\"values\":[101,102,103]}", JSON.toJSONString(bean)); + assertEquals("{\"values\":[101,102,103]}", new String(JSON.toJSONBytes(bean))); + assertEquals("{\n" + + "\t\"values\":[101,102,103]\n" + + "}", JSON.toJSONString(bean, JSONWriter.Feature.PrettyFormat)); + assertEquals("{\n" + + "\t\"values\":[101,102,103]\n" + + "}", new String(JSON.toJSONBytes(bean, JSONWriter.Feature.PrettyFormat))); + } } diff --git a/core/src/test/java/com/alibaba/fastjson2/primitves/LongValueArrayField1Test.java b/core/src/test/java/com/alibaba/fastjson2/primitves/LongValueArrayField1Test.java index 2dd282dcc6..30f9c8918c 100644 --- a/core/src/test/java/com/alibaba/fastjson2/primitves/LongValueArrayField1Test.java +++ b/core/src/test/java/com/alibaba/fastjson2/primitves/LongValueArrayField1Test.java @@ -1,6 +1,8 @@ package com.alibaba.fastjson2.primitves; +import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONReader; +import com.alibaba.fastjson2.JSONWriter; import com.alibaba.fastjson2.TestUtils; import com.alibaba.fastjson2.reader.FieldReader; import com.alibaba.fastjson2.reader.ObjectReader; @@ -73,4 +75,19 @@ public void test_final_0() throws Exception { } } } + + @Test + public void test_write_0() throws Exception { + LongValueArrayField1 bean = new LongValueArrayField1(); + bean.values = new long[] {101, 102, 103}; + assertEquals("{\"values\":[101,102,103]}", JSON.toJSONString(bean)); + assertEquals("{\"values\":[101,102,103]}", new String(JSON.toJSONBytes(bean))); + + assertEquals("{\n" + + "\t\"values\":[101,102,103]\n" + + "}", JSON.toJSONString(bean, JSONWriter.Feature.PrettyFormat)); + assertEquals("{\n" + + "\t\"values\":[101,102,103]\n" + + "}", new String(JSON.toJSONBytes(bean, JSONWriter.Feature.PrettyFormat))); + } } diff --git a/incubator-vector/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16Vector.java b/incubator-vector/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16Vector.java index f1da860073..db70ad5929 100644 --- a/incubator-vector/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16Vector.java +++ b/incubator-vector/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16Vector.java @@ -269,7 +269,7 @@ public void writeString(String str) { } @Override - public void writeStringLatin1(byte[] value) { + protected void writeStringLatin1(byte[] value) { if (value == null) { if (isEnabled(Feature.NullAsDefaultValue.mask | Feature.WriteNullStringAsEmpty.mask)) { writeString(""); diff --git a/incubator-vector/src/main/java/com/alibaba/fastjson2/JSONWriterUTF8Vector.java b/incubator-vector/src/main/java/com/alibaba/fastjson2/JSONWriterUTF8Vector.java index e051f2e611..612a19ea0c 100644 --- a/incubator-vector/src/main/java/com/alibaba/fastjson2/JSONWriterUTF8Vector.java +++ b/incubator-vector/src/main/java/com/alibaba/fastjson2/JSONWriterUTF8Vector.java @@ -302,7 +302,7 @@ public void writeString(String str) { } @Override - public void writeStringLatin1(byte[] value) { + protected void writeStringLatin1(byte[] value) { if (value == null) { if (isEnabled(JSONWriter.Feature.NullAsDefaultValue.mask | JSONWriter.Feature.WriteNullStringAsEmpty.mask)) { writeString("");