Repository: alibaba/fastjson2
Pull request #3243 (2025-01-01 09:27:27)

deserialize enum support toString value
### What this PR does / why we need it?



### Summary of your change



#### Please indicate you've done the following:

- [ ] Made sure tests are passing and test coverage is added if needed.
- [ ] Made sure commit message follow the rule of [Conventional Commits specification](https://www.conventionalcommits.org/).
- [ ] Considered the docs impact and opened a new docs issue or PR with docs changes if needed.



Patch:
diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONWriter.java b/core/src/main/java/com/alibaba/fastjson2/JSONWriter.java
index e0606f3dc..ce37b465e 100644
--- a/core/src/main/java/com/alibaba/fastjson2/JSONWriter.java
+++ b/core/src/main/java/com/alibaba/fastjson2/JSONWriter.java
@@ -2734,21 +2734,6 @@ public abstract class JSONWriter
         }
     }
 
-    protected final int newCapacity(int minCapacity, int oldCapacity) {
-        int newCapacity = oldCapacity + (oldCapacity >> 1);
-        if (newCapacity - minCapacity < 0) {
-            newCapacity = minCapacity;
-        }
-        if (newCapacity > maxArraySize) {
-            if (minCapacity < maxArraySize) {
-                newCapacity = maxArraySize;
-            } else {
-                throw new OutOfMemoryError("try enabling LargeObject feature instead");
-            }
-        }
-        return newCapacity;
-    }
-
     public Object getAttachment() {
         return attachment;
     }
diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONWriterJSONB.java b/core/src/main/java/com/alibaba/fastjson2/JSONWriterJSONB.java
index 6e41769c8..b5994d9e0 100644
--- a/core/src/main/java/com/alibaba/fastjson2/JSONWriterJSONB.java
+++ b/core/src/main/java/com/alibaba/fastjson2/JSONWriterJSONB.java
@@ -1153,7 +1153,17 @@ final class JSONWriterJSONB
     }
 
     private void grow0(int minCapacity) {
-        bytes = Arrays.copyOf(bytes, newCapacity(minCapacity, bytes.length));
+        int oldCapacity = bytes.length;
+        int newCapacity = oldCapacity + (oldCapacity >> 1);
+        if (newCapacity - minCapacity < 0) {
+            newCapacity = minCapacity;
+        }
+        if (newCapacity > maxArraySize) {
+            throw new OutOfMemoryError("try enabling LargeObject feature instead");
+        }
+
+        // minCapacity is usually close to size, so this is a win:
+        bytes = Arrays.copyOf(bytes, newCapacity);
     }
 
     @Override
diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16.java b/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16.java
index a8add297e..97383c1c2 100644
--- a/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16.java
+++ b/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16.java
@@ -2001,7 +2001,17 @@ class JSONWriterUTF16
     }
 
     private char[] grow(int minCapacity) {
-        return chars = Arrays.copyOf(chars, newCapacity(minCapacity, chars.length));
+        int oldCapacity = chars.length;
+        int newCapacity = oldCapacity + (oldCapacity >> 1);
+        if (newCapacity - minCapacity < 0) {
+            newCapacity = minCapacity;
+        }
+        if (newCapacity - maxArraySize > 0) {
+            throw new OutOfMemoryError("try enabling LargeObject feature instead");
+        }
+
+        // minCapacity is usually close to size, so this is a win:
+        return chars = Arrays.copyOf(chars, newCapacity);
     }
 
     public final void writeInt32(int[] value) {
diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF8.java b/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF8.java
index dc0e848ea..7d1e25ea7 100644
--- a/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF8.java
+++ b/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF8.java
@@ -2084,8 +2084,17 @@ class JSONWriterUTF8
     }
 
     private void grow0(int minCapacity) {
+        int oldCapacity = bytes.length;
+        int newCapacity = oldCapacity + (oldCapacity >> 1);
+        if (newCapacity - minCapacity < 0) {
+            newCapacity = minCapacity;
+        }
+        if (newCapacity - maxArraySize > 0) {
+            throw new OutOfMemoryError("try enabling LargeObject feature instead");
+        }
+
         // minCapacity is usually close to size, so this is a win:
-        bytes = Arrays.copyOf(bytes, newCapacity(minCapacity, bytes.length));
+        bytes = Arrays.copyOf(bytes, newCapacity);
     }
 
     public final void writeInt32(int[] values) {
diff --git a/core/src/main/java/com/alibaba/fastjson2/reader/ObjectReaderCreator.java b/core/src/main/java/com/alibaba/fastjson2/reader/ObjectReaderCreator.java
index 90ea35e66..56db7085e 100644
--- a/core/src/main/java/com/alibaba/fastjson2/reader/ObjectReaderCreator.java
+++ b/core/src/main/java/com/alibaba/fastjson2/reader/ObjectReaderCreator.java
@@ -3231,6 +3231,13 @@ public class ObjectReaderCreator {
             String name = e.name();
             long hashLCase = Fnv.hashCode64LCase(name);
             enumMap.putIfAbsent(hashLCase, e);
+
+            String str = e.toString();
+            if (name.equals(str)) {
+                continue;
+            }
+            long hashLCaseStr = Fnv.hashCode64LCase(str);
+            enumMap.putIfAbsent(hashLCaseStr, e);
         }
 
         long[] enumNameHashCodes = new long[enumMap.size()];
diff --git a/core/src/main/java/com/alibaba/fastjson2/support/csv/CSVWriterUTF16.java b/core/src/main/java/com/alibaba/fastjson2/support/csv/CSVWriterUTF16.java
index dc283e388..872450822 100644
--- a/core/src/main/java/com/alibaba/fastjson2/support/csv/CSVWriterUTF16.java
+++ b/core/src/main/java/com/alibaba/fastjson2/support/csv/CSVWriterUTF16.java
@@ -150,9 +150,8 @@ final class CSVWriterUTF16
         for (int i = 0; i < len; ) {
             char ch = str.charAt(i++);
             if (ch == '"') {
-                chars[off] = '"';
-                chars[off + 1] = '"';
-                off += 2;
+                chars[off++] = '"';
+                chars[off++] = '"';
             } else {
                 chars[off++] = ch;
             }
@@ -161,8 +160,8 @@ final class CSVWriterUTF16
                 off = this.off;
             }
         }
-        chars[off] = '"';
-        this.off = off + 1;
+        chars[off++] = '"';
+        this.off = off;
     }
 
     public void writeInt32(int intValue) {
@@ -228,13 +227,9 @@ final class CSVWriterUTF16
             return;
         }
 
-        int off = this.off;
-        char[] chars = this.chars;
-        if (off + 24 > chars.length) {
-            flush();
-            off = 0;
-        }
-        this.off = IOUtils.writeDecimal(chars, off, unscaledVal, scale);
+        checkCapacity(24);
+
+        off = IOUtils.writeDecimal(chars, off, unscaledVal, scale);
     }
 
     void writeRaw(char[] chars) {
@@ -258,15 +253,11 @@ final class CSVWriterUTF16
         }
 
         // "yyyy-MM-dd HH:mm:ss"
-        int off = this.off;
-        char[] chars = this.chars;
-        if (off + 19 > chars.length) {
-            flush();
-            off = 0;
-        }
+        checkCapacity(19);
+
         off = IOUtils.writeLocalDate(chars, off, ldt.getYear(), ldt.getMonthValue(), ldt.getDayOfMonth());
         chars[off++] = ' ';
-        this.off = IOUtils.writeLocalTime(chars, off, ldt.toLocalTime());
+        off = IOUtils.writeLocalTime(chars, off, ldt.toLocalTime());
     }
 
     protected void writeRaw(String str) {
diff --git a/core/src/main/java/com/alibaba/fastjson2/support/csv/CSVWriterUTF8.java b/core/src/main/java/com/alibaba/fastjson2/support/csv/CSVWriterUTF8.java
index a941dee8a..f31c67ef4 100644
--- a/core/src/main/java/com/alibaba/fastjson2/support/csv/CSVWriterUTF8.java
+++ b/core/src/main/java/com/alibaba/fastjson2/support/csv/CSVWriterUTF8.java
@@ -184,9 +184,8 @@ final class CSVWriterUTF8
         bytes[off++] = '"';
         for (byte ch : utf8) {
             if (ch == '"') {
-                bytes[off] = '"';
-                bytes[off + 1] = '"';
-                off += 2;
+                bytes[off++] = '"';
+                bytes[off++] = '"';
             } else {
                 bytes[off++] = ch;
             }
@@ -224,13 +223,9 @@ final class CSVWriterUTF8
             return;
         }
 
-        int off = this.off;
-        byte[] bytes = this.bytes;
-        if (off + 24 > bytes.length) {
-            flush();
-            off = 0;
-        }
-        this.off = IOUtils.writeDecimal(bytes, off, unscaledVal, scale);
+        checkCapacity(24);
+
+        off = IOUtils.writeDecimal(bytes, off, unscaledVal, scale);
     }
 
     private void writeRaw(byte[] strBytes) {
@@ -263,15 +258,11 @@ final class CSVWriterUTF8
         }
 
         // "yyyy-MM-dd HH:mm:ss"
-        int off = this.off;
-        byte[] bytes = this.bytes;
-        if (off + 19 > bytes.length) {
-            flush();
-            off = 0;
-        }
+        checkCapacity(19);
+
         off = IOUtils.writeLocalDate(bytes, off, ldt.getYear(), ldt.getMonthValue(), ldt.getDayOfMonth());
         bytes[off++] = ' ';
-        this.off = IOUtils.writeLocalTime(bytes, off, ldt.toLocalTime());
+        off = IOUtils.writeLocalTime(bytes, off, ldt.toLocalTime());
     }
 
     void checkCapacity(int incr) {


Test patch:
diff --git a/core/src/test/java/com/alibaba/fastjson2/issues_2800/Issue2820.java b/core/src/test/java/com/alibaba/fastjson2/issues_2800/Issue2820.java
index 5ce70aaf8..378e37aca 100644
--- a/core/src/test/java/com/alibaba/fastjson2/issues_2800/Issue2820.java
+++ b/core/src/test/java/com/alibaba/fastjson2/issues_2800/Issue2820.java
@@ -72,4 +72,46 @@ public class Issue2820 {
             return this.value;
         }
     }
+
+    public enum CityGMLVersion1 {
+        v3_0("3.0"),
+        v2_0("2.0"),
+        v1_0("1.0");
+
+        private final String value;
+
+        CityGMLVersion1(String value) {
+            this.value = value;
+        }
+
+        public String toValue() {
+            return this.value;
+        }
+
+        public static CityGMLVersion1 fromValue(String value) {
+            for (CityGMLVersion1 v : values()) {
+                if (v.value.equals(value)) {
+                    return v;
+                }
+            }
+            return null;
+        }
+
+        public String toString() {
+            return this.value;
+        }
+    }
+
+    @Test
+    public void test1() {
+        Foo1 foo = JSON.parseObject("{\n" +
+                "  \"version\": \"2.0\"\n" +
+                "}", Foo1.class);
+
+        assertEquals(CityGMLVersion1.v2_0, foo.version);
+    }
+
+    public static class Foo1 {
+        public CityGMLVersion1 version;
+    }
 }
diff --git a/core/src/test/java/com/alibaba/fastjson2/issues_2900/Issue2955.java b/core/src/test/java/com/alibaba/fastjson2/issues_2900/Issue2955.java
deleted file mode 100644
index 61e5599d8..000000000
--- a/core/src/test/java/com/alibaba/fastjson2/issues_2900/Issue2955.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.alibaba.fastjson2.issues_2900;
-
-import com.alibaba.fastjson2.JSONObject;
-import org.junit.jupiter.api.Test;
-
-import java.util.Random;
-
-public class Issue2955 {
-    @Test
-    public void test() {
-        String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
-        long STRING_LENGTH = 63L * 1024L * 1024L;
-
-        JSONObject jsonObject = new JSONObject();
-        System.out.println(STRING_LENGTH);
-        // 生成64 * 1024 * 1024长度的字符串
-        Random random = new Random();
-        StringBuilder largeStringBuilder = new StringBuilder();
-        for (long i = 0; i < STRING_LENGTH; i++) {
-            int index = random.nextInt(CHARACTERS.length());
-            largeStringBuilder.append(CHARACTERS.charAt(index));
-        }
-        String largeString = largeStringBuilder.toString();
-        jsonObject.put("largeString", largeString);
-        String jsonString = jsonObject.toJSONString();
-    }
-}
diff --git a/core/src/test/java/com/alibaba/fastjson2/issues_3200/Issue3210.java b/core/src/test/java/com/alibaba/fastjson2/issues_3200/Issue3210.java
index 1ca0844a2..c5b74798a 100644
--- a/core/src/test/java/com/alibaba/fastjson2/issues_3200/Issue3210.java
+++ b/core/src/test/java/com/alibaba/fastjson2/issues_3200/Issue3210.java
@@ -1,11 +1,9 @@
 package com.alibaba.fastjson2.issues_3200;
 
-import com.alibaba.fastjson2.JSON;
 import com.alibaba.fastjson2.JSONObject;
 import lombok.Data;
 import org.junit.jupiter.api.Test;
 
-import java.nio.charset.StandardCharsets;
 import java.util.Date;
 
 import static org.junit.jupiter.api.Assertions.assertNotNull;
@@ -19,66 +17,7 @@ public class Issue3210 {
     @Test
     public void test() {
         String s = "{\"time\":\"2024-12-04T20:43:15.000000999\"}";
-        {
-            Bean bean = JSONObject.parseObject(s, Bean.class);
-            assertNotNull(bean.time);
-        }
-        {
-            Bean bean = JSON.parseObject(s.getBytes(StandardCharsets.UTF_8), Bean.class);
-            assertNotNull(bean.time);
-        }
-        {
-            Bean bean = JSON.parseObject(s.toCharArray(), Bean.class);
-            assertNotNull(bean.time);
-        }
-    }
-
-    @Data
-    private static class Bean1 {
-        private Date time;
-    }
-
-    @Test
-    public void test1() {
-        String s = "{\"time\":\"2024-12-04T20:43:15.000000999\"}";
-        {
-            Bean1 bean = JSONObject.parseObject(s, Bean1.class);
-            assertNotNull(bean.time);
-        }
-        {
-            byte[] bytes = s.getBytes();
-            Bean1 bean = JSON.parseObject(bytes, 0, bytes.length, Bean1.class);
-            assertNotNull(bean.time);
-        }
-        {
-            Bean1 bean = JSON.parseObject(s.toCharArray(), Bean1.class);
-            assertNotNull(bean.time);
-        }
-    }
-
-    public static class Bean2 {
-        public final Date time;
-
-        public Bean2(Date time) {
-            this.time = time;
-        }
-    }
-
-    @Test
-    public void test2() {
-        String s = "{\"time\":\"2024-12-04T20:43:15.000000999\"}";
-        {
-            Bean2 bean = JSONObject.parseObject(s, Bean2.class);
-            assertNotNull(bean.time);
-        }
-        {
-            byte[] bytes = s.getBytes();
-            Bean2 bean = JSON.parseObject(bytes, 0, bytes.length, Bean2.class);
-            assertNotNull(bean.time);
-        }
-        {
-            Bean2 bean = JSON.parseObject(s.toCharArray(), Bean2.class);
-            assertNotNull(bean.time);
-        }
+        Bean bean = JSONObject.parseObject(s, Bean.class);
+        assertNotNull(bean.time);
     }
 }
diff --git a/core/src/test/java/com/alibaba/fastjson2/support/csv/CapacityTest.java b/core/src/test/java/com/alibaba/fastjson2/support/csv/CapacityTest.java
deleted file mode 100644
index 0b4a9ab25..000000000
--- a/core/src/test/java/com/alibaba/fastjson2/support/csv/CapacityTest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package com.alibaba.fastjson2.support.csv;
-
-import org.jetbrains.annotations.NotNull;
-import org.junit.jupiter.api.Test;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.util.Arrays;
-import java.util.Random;
-
-public class CapacityTest {
-    @Test
-    public void writeString_utf16() throws Exception {
-        try (CSVWriterUTF16 writer = (CSVWriterUTF16) CSVWriter.of(new NoopWriter())) {
-            for (int i = 0; i < 100_000; i++) {
-                writer.writeString("a");
-            }
-        }
-        try (CSVWriterUTF16 writer = (CSVWriterUTF16) CSVWriter.of(new NoopWriter())) {
-            for (int i = 0; i < 100_000; i++) {
-                writer.writeString("\n");
-                writer.writeString("\r");
-                writer.writeString("\"");
-            }
-        }
-        try (CSVWriterUTF16 writer = (CSVWriterUTF16) CSVWriter.of(new NoopWriter())) {
-            writer.writeString(
-                    repeat('x', 100_000));
-            writer.writeString(
-                    repeat(',', 100_000));
-        }
-        try (CSVWriterUTF16 writer = (CSVWriterUTF16) CSVWriter.of(new NoopWriter())) {
-            Random r = new Random();
-            for (int i = 0; i < 100_000; i++) {
-                writer.writeString(
-                        repeat('x', r.nextInt(1000)));
-            }
-        }
-    }
-
-    @Test
-    public void writeString_utf8() throws Exception {
-        try (CSVWriterUTF8 writer = (CSVWriterUTF8) CSVWriter.of(new NoopOutputStream())) {
-            for (int i = 0; i < 100_000; i++) {
-                writer.writeString("a");
-            }
-        }
-        try (CSVWriterUTF8 writer = (CSVWriterUTF8) CSVWriter.of(new NoopOutputStream())) {
-            for (int i = 0; i < 100_000; i++) {
-                writer.writeString("\n");
-                writer.writeString("\r");
-                writer.writeString("\"");
-            }
-        }
-        try (CSVWriterUTF8 writer = (CSVWriterUTF8) CSVWriter.of(new NoopOutputStream())) {
-            writer.writeString(
-                    repeat('x', 100_000));
-            writer.writeString(
-                    repeat(',', 100_000));
-        }
-        try (CSVWriterUTF8 writer = (CSVWriterUTF8) CSVWriter.of(new NoopOutputStream())) {
-            Random r = new Random();
-            for (int i = 0; i < 100_000; i++) {
-                writer.writeString(
-                        repeat('x', r.nextInt(1000)));
-            }
-        }
-    }
-
-    static String repeat(char c, int count) {
-        char[] chars = new char[count];
-        Arrays.fill(chars, c);
-        return new String(chars);
-    }
-
-    static class NoopWriter
-            extends Writer {
-        @Override
-        public void write(@NotNull char[] cbuf, int off, int len) throws IOException {
-        }
-
-        @Override
-        public void flush() throws IOException {
-        }
-
-        @Override
-        public void close() throws IOException {
-        }
-    }
-
-    static class NoopOutputStream
-            extends java.io.OutputStream {
-        @Override
-        public void write(int b) throws IOException {
-        }
-    }
-}
diff --git a/fastjson1-compatible/src/test/java/com/alibaba/fastjson/v2issues/Issue3157.java b/fastjson1-compatible/src/test/java/com/alibaba/fastjson/v2issues/Issue3157.java
deleted file mode 100644
index 7b7795940..000000000
--- a/fastjson1-compatible/src/test/java/com/alibaba/fastjson/v2issues/Issue3157.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.alibaba.fastjson.v2issues;
-
-import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.serializer.SerializeConfig;
-import com.alibaba.fastjson.serializer.ToStringSerializer;
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-public class Issue3157 {
-    public static class People {
-        private Integer age;
-
-        private Long hairNums;
-
-        private String name;
-
-        public People(Integer age, String name, Long hairNums) {
-            this.age = age;
-            this.name = name;
-            this.hairNums = hairNums;
-        }
-
-        public Integer getAge() {
-            return age;
-        }
-
-        public String getName() {
-            return name;
-        }
-
-        public Long getHairNums() {
-            return hairNums;
-        }
-    }
-
-    @Test
-    public void test() {
-        SerializeConfig stringSerializeConfig = new SerializeConfig();
-        stringSerializeConfig.put(Integer.class, ToStringSerializer.instance);
-        stringSerializeConfig.put(Long.class, ToStringSerializer.instance);
-
-        People one = new People(10, "aaa", 10000000L);
-        assertEquals(
-                "{\"age\":\"10\",\"hairNums\":\"10000000\",\"name\":\"aaa\"}",
-                JSON.toJSONString(one, stringSerializeConfig));
-    }
-}