Repository: alibaba/fastjson2
Pull request #3496 (2025-04-14 20:07:18)

Bump com.google.guava:guava from 33.4.6-jre to 33.4.8-jre
Bumps [com.google.guava:guava](https://github.com/google/guava) from 33.4.6-jre to 33.4.8-jre.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/google/guava/releases">com.google.guava:guava's releases</a>.</em></p>
<blockquote>
<h2>33.4.8</h2>
<p>Guava 33.4.8 fixes a problem that we introduced while starting to migrate <code>guava-android</code> off <code>Unsafe</code> in <a href="https://github.com/google/guava/releases/tag/v33.4.7">33.4.7</a>.</p>
<p>Even if you're not upgrading from Guava 33.4.0 or earlier, still read <a href="https://github.com/google/guava/releases/tag/v33.4.1">the release notes for Guava 33.4.1</a>. Those release notes contain information about the effects of Guava 33.4.5 and higher on the module system.</p>
<h3>Maven</h3>
<pre lang="xml"><code>&lt;dependency&gt;
  &lt;groupId&gt;com.google.guava&lt;/groupId&gt;
  &lt;artifactId&gt;guava&lt;/artifactId&gt;
  &lt;version&gt;33.4.8-jre&lt;/version&gt;
  &lt;!-- or, for Android: --&gt;
  &lt;version&gt;33.4.8-android&lt;/version&gt;
&lt;/dependency&gt;
</code></pre>
<h3>Jar files</h3>
<ul>
<li><a href="https://repo1.maven.org/maven2/com/google/guava/guava/33.4.8-jre/guava-33.4.8-jre.jar">33.4.8-jre.jar</a></li>
<li><a href="https://repo1.maven.org/maven2/com/google/guava/guava/33.4.8-android/guava-33.4.8-android.jar">33.4.8-android.jar</a></li>
</ul>
<p>Guava requires <a href="https://github.com/google/guava/wiki/UseGuavaInYourBuild#what-about-guavas-own-dependencies">one runtime dependency</a>, which you can download here:</p>
<ul>
<li><a href="https://repo1.maven.org/maven2/com/google/guava/failureaccess/1.0.3/failureaccess-1.0.3.jar">failureaccess-1.0.3.jar</a></li>
</ul>
<h3>Javadoc</h3>
<ul>
<li><a href="https://guava.dev/releases/33.4.8-jre/api/docs/">33.4.8-jre</a></li>
<li><a href="https://guava.dev/releases/33.4.8-android/api/docs/">33.4.8-android</a></li>
</ul>
<h3>JDiff</h3>
<ul>
<li><a href="https://guava.dev/releases/33.4.8-jre/api/diffs/">33.4.8-jre vs. 33.4.7-jre</a></li>
<li><a href="https://guava.dev/releases/33.4.8-android/api/diffs/">33.4.8-android vs. 33.4.7-android</a></li>
<li><a href="https://guava.dev/releases/33.4.8-android/api/androiddiffs/">33.4.8-android vs. 33.4.8-jre</a></li>
</ul>
<h3>Changelog</h3>
<ul>
<li><code>util.concurrent</code>: Removed our <code>VarHandle</code> code from <code>guava-android</code>. While the code was never used at runtime under Android, it was causing <a href="https://redirect.github.com/google/guava/issues/7769">problems under the Android Gradle Plugin</a> with a <code>minSdkVersion</code> below 26. To continue to avoid <code>sun.misc.Unsafe</code> under the JVM, <code>guava-android</code> will now always use <code>AtomicReferenceFieldUpdater</code> when run there. (75da92419a)</li>
</ul>
<h2>33.4.7</h2>
<p><strong>Prefer to upgrade straight to <a href="https://github.com/google/guava/releases/tag/v33.4.8">33.4.8</a>:</strong> 33.4.7 <a href="https://redirect.github.com/google/guava/issues/7769">breaks the build of Android apps with a minSdkVersion below 26</a>. We will publish a fixed version soon. This problem is fixed in 33.4.8.</p>
<p>Guava 33.4.7, like <a href="https://github.com/google/guava/releases/tag/v33.4.6">33.4.6</a>, fixes two problems that we introduced while modularizing Guava and migrating off <code>Unsafe</code> in <a href="https://github.com/google/guava/releases/tag/v33.4.5">33.4.5</a>.</p>
<p>Even if you're not upgrading from Guava 33.4.0 or earlier, still read <a href="https://github.com/google/guava/releases/tag/v33.4.1">the release notes for Guava 33.4.1</a>. Those release notes contain information about the effects of Guava 33.4.5 and higher on the module system.</p>
<h3>Maven</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a href="https://github.com/google/guava/commits">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=com.google.guava:guava&package-manager=maven&previous-version=33.4.6-jre&new-version=33.4.8-jre)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Patch:
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index f198350a1..933aa995b 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -18,7 +18,7 @@ jobs:
     timeout-minutes: 20
     strategy:
       matrix:
-        os: [ ubuntu-20.04, windows-latest, macos-latest ]
+        os: [ ubuntu-24.04, windows-latest, macos-latest ]
         java: [ 8, 11, 17, 21 ]
       fail-fast: false
       max-parallel: 16
diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONArray.java b/core/src/main/java/com/alibaba/fastjson2/JSONArray.java
index cb379ce6d..c3300de5f 100644
--- a/core/src/main/java/com/alibaba/fastjson2/JSONArray.java
+++ b/core/src/main/java/com/alibaba/fastjson2/JSONArray.java
@@ -210,7 +210,7 @@ public class JSONArray
             return writerAdapter.toJSONObject(value);
         }
 
-        return null;
+        return (JSONObject) JSON.toJSON(value);
     }
 
     /**
diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONWriter.java b/core/src/main/java/com/alibaba/fastjson2/JSONWriter.java
index 2cb955958..942a846e6 100644
--- a/core/src/main/java/com/alibaba/fastjson2/JSONWriter.java
+++ b/core/src/main/java/com/alibaba/fastjson2/JSONWriter.java
@@ -224,6 +224,9 @@ public abstract class JSONWriter
     }
 
     public final String setPath0(int index, Object object) {
+        if (path == null) {
+            return null;
+        }
         this.path = index == 0
                 ? (path.child0 != null ? path.child0 : (path.child0 = new Path(path, index)))
                 : index == 1
diff --git a/core/src/main/java/com/alibaba/fastjson2/reader/FieldReaderObject.java b/core/src/main/java/com/alibaba/fastjson2/reader/FieldReaderObject.java
index ba79f51a6..19fad388d 100644
--- a/core/src/main/java/com/alibaba/fastjson2/reader/FieldReaderObject.java
+++ b/core/src/main/java/com/alibaba/fastjson2/reader/FieldReaderObject.java
@@ -182,7 +182,9 @@ public class FieldReaderObject<T>
                 jsonReader.skipValue();
                 return;
             } else if ((contextFeatures & JSONReader.Feature.ErrorOnNoneSerializable.mask) != 0) {
-                throw new JSONException("not support none-Serializable");
+                if (fieldClass != Object.class || (jsonReader.isObject() || jsonReader.isArray())) {
+                    throw new JSONException("not support none-Serializable");
+                }
             }
         }
 
diff --git a/docs/benchmark/benchmark_2.0.12.md b/docs/benchmark/benchmark_2.0.12.md
index 06517c066..62436148a 100644
--- a/docs/benchmark/benchmark_2.0.12.md
+++ b/docs/benchmark/benchmark_2.0.12.md
@@ -50,7 +50,7 @@ Bean bean = JSON.parseJSONObject(str, Bean.class);
 
 这个场景是fastjson1最强的场景；
 
-在ecs.c7.xlarge-oracle-jdk1.8.0_341_x64环境中，只相当于只相当于fastjson2的76.16%;jackson则只相当于fastjson2的41.62%; gson是fastjson2的34.44%.
+在ecs.c7.xlarge-oracle-jdk1.8.0_341_x64环境中，只相当于fastjson2的76.16%；jackson则只相当于fastjson2的41.62%；gson是fastjson2的34.44%。
 
 性能排序如下：
 ```java
@@ -224,7 +224,7 @@ byte[] utf8Bytes = ...;
 Bean bean = JSON.parseJSONObject(utf8Bytes, Bean.class);
 ```
 
-这个场景fastjson2同样表现出了卓越的性能；在JDK8下，fastjson1和jackson的性能分别之后fastjson2的50.49%和63.22%;
+这个场景fastjson2同样表现出了卓越的性能；在JDK8下，fastjson1和jackson的性能分别之后fastjson2的50.49%和63.22%；
 gson不直接支持输入utf8Bytes，需要先构造字符串，性能只有fastjson2的35%。
 
 性能排序如下：
@@ -312,7 +312,7 @@ byte[] utf8Bytes = ...;
 JSONObject jsonObject = JSON.parseJSONObject(utf8Bytes);
 ```
 
-这个场景fastjson2同样表现出了卓越的性能；在JDK8下，fastjson1和jackson的性能分别之后fastjson2的50.49%和63.22%;
+这个场景fastjson2同样表现出了卓越的性能；在JDK8下，fastjson1和jackson的性能分别之后fastjson2的50.49%和63.22%；
 gson不直接支持输入utf8Bytes，需要先构造字符串，性能只有fastjson2的35%。
 
 性能排序如下：
diff --git a/example-graalvm-native/pom.xml b/example-graalvm-native/pom.xml
index c4b1ef04f..21c722201 100644
--- a/example-graalvm-native/pom.xml
+++ b/example-graalvm-native/pom.xml
@@ -103,7 +103,7 @@
         <dependency>
             <groupId>org.junit.platform</groupId>
             <artifactId>junit-platform-launcher</artifactId>
-            <version>1.12.1</version>
+            <version>1.12.2</version>
             <scope>test</scope>
         </dependency>
     </dependencies>
diff --git a/pom.xml b/pom.xml
index 1ddaff675..00ce69f01 100644
--- a/pom.xml
+++ b/pom.xml
@@ -53,7 +53,7 @@
         <!-- https://kotlinlang.org/docs/maven.html#specifying-compiler-options -->
         <kotlin.compiler.apiVersion>1.9</kotlin.compiler.apiVersion>
 
-        <junit5.version>5.12.1</junit5.version>
+        <junit5.version>5.12.2</junit5.version>
         <kotest.version>5.5.5</kotest.version>
         <jmh.version>1.37</jmh.version>
 
@@ -192,12 +192,12 @@
             <dependency>
                 <groupId>com.google.code.gson</groupId>
                 <artifactId>gson</artifactId>
-                <version>2.12.1</version>
+                <version>2.13.0</version>
             </dependency>
             <dependency>
                 <groupId>com.google.guava</groupId>
                 <artifactId>guava</artifactId>
-                <version>33.4.6-jre</version>
+                <version>33.4.8-jre</version>
             </dependency>
             <dependency>
                 <groupId>com.google.protobuf</groupId>


Test patch:
diff --git a/core/src/test/java/com/alibaba/fastjson2/issues_3400/Issue3419.java b/core/src/test/java/com/alibaba/fastjson2/issues_3400/Issue3419.java
new file mode 100644
index 000000000..c600b5c89
--- /dev/null
+++ b/core/src/test/java/com/alibaba/fastjson2/issues_3400/Issue3419.java
@@ -0,0 +1,30 @@
+package com.alibaba.fastjson2.issues_3400;
+
+import com.alibaba.fastjson2.JSONArray;
+import com.alibaba.fastjson2.JSONObject;
+import org.junit.jupiter.api.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class Issue3419 {
+    @Test
+    public void test() {
+        Map<String, Object> map = new HashMap<>();
+        map.put("str", new float[] {1.0f, 1.0f, 1.0f, 1.0f, 1.0f});
+
+        com.alibaba.fastjson.JSONObject jo1 = new com.alibaba.fastjson.JSONObject();
+        com.alibaba.fastjson.JSONArray ja1 = new com.alibaba.fastjson.JSONArray();
+        ja1.addAll(map.entrySet());
+        jo1.put("content", ja1);
+
+        JSONObject jo2 = new JSONObject();
+        JSONArray ja2 = new JSONArray();
+        ja2.addAll(map.entrySet());
+        jo2.put("content", ja2);
+
+        assertEquals(jo1.getJSONArray("content").getJSONObject(0), jo2.getJSONArray("content").getJSONObject(0));
+    }
+}
diff --git a/core/src/test/java/com/alibaba/fastjson2/issues_3400/Issue3432.java b/core/src/test/java/com/alibaba/fastjson2/issues_3400/Issue3432.java
new file mode 100644
index 000000000..e278b3c92
--- /dev/null
+++ b/core/src/test/java/com/alibaba/fastjson2/issues_3400/Issue3432.java
@@ -0,0 +1,31 @@
+package com.alibaba.fastjson2.issues_3400;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONWriter;
+import lombok.Data;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class Issue3432 {
+    @Test
+    public void test_toJSON() {
+        List<Node> nodes = new ArrayList<>();
+        Node node = new Node();
+        node.setGradeId("123");
+        node.setPrivilegeIds(Arrays.asList("1", "2"));
+        nodes.add(node);
+
+        assertEquals(com.alibaba.fastjson.JSON.toJSON(nodes), JSON.toJSON(nodes, JSONWriter.Feature.ReferenceDetection));
+    }
+
+    @Data
+    public static class Node {
+        private String gradeId;
+        private List<String> privilegeIds;
+    }
+}
diff --git a/core/src/test/java/com/alibaba/fastjson2/issues_3400/Issue3499.java b/core/src/test/java/com/alibaba/fastjson2/issues_3400/Issue3499.java
new file mode 100644
index 000000000..6c54af25e
--- /dev/null
+++ b/core/src/test/java/com/alibaba/fastjson2/issues_3400/Issue3499.java
@@ -0,0 +1,44 @@
+package com.alibaba.fastjson2.issues_3400;
+
+import com.alibaba.fastjson2.JSONB;
+import com.alibaba.fastjson2.JSONReader;
+import com.alibaba.fastjson2.JSONWriter;
+import com.alibaba.fastjson2.filter.ContextAutoTypeBeforeHandler;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import org.junit.jupiter.api.Test;
+
+import java.io.Serializable;
+
+public class Issue3499 {
+    @Test
+    public void test() {
+        Message<String> obj = new Message<>("Hello");
+        byte[] bytes = JSONB.toBytes(obj, JSONWriter.Feature.WriteClassName,
+                JSONWriter.Feature.FieldBased,
+                JSONWriter.Feature.ErrorOnNoneSerializable,
+                JSONWriter.Feature.ReferenceDetection,
+                JSONWriter.Feature.WriteNulls,
+                JSONWriter.Feature.NotWriteDefaultValue,
+                JSONWriter.Feature.NotWriteHashMapArrayListClassName,
+                JSONWriter.Feature.WriteNameAsSymbol);
+        ContextAutoTypeBeforeHandler handler = new ContextAutoTypeBeforeHandler(true, obj.getClass());
+        Object result = JSONB.parseObject(bytes, obj.getClass(), handler,
+                JSONReader.Feature.UseDefaultConstructorAsPossible,
+                JSONReader.Feature.ErrorOnNoneSerializable,
+                JSONReader.Feature.IgnoreAutoTypeNotMatch,
+                JSONReader.Feature.UseNativeObject,
+                JSONReader.Feature.FieldBased);
+    }
+
+    @Getter
+    @Setter
+    @NoArgsConstructor
+    @AllArgsConstructor
+    static class Message<T>
+            implements Serializable {
+        T msg;
+    }
+}