Repository: alibaba/fastjson2
Pull request #3600 (2025-06-24 02:29:11)

fix hutool's Tree deserialization data loss，issue #2375
### 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/reader/ObjectReaderBaseModule.java b/core/src/main/java/com/alibaba/fastjson2/reader/ObjectReaderBaseModule.java
index f139c7e7a..0c2d3a9e0 100644
--- a/core/src/main/java/com/alibaba/fastjson2/reader/ObjectReaderBaseModule.java
+++ b/core/src/main/java/com/alibaba/fastjson2/reader/ObjectReaderBaseModule.java
@@ -2176,6 +2176,8 @@ public class ObjectReaderBaseModule
                     case "com.google.common.collect.ImmutableSet":
                     case "com.google.common.collect.SingletonImmutableSet":
                         return ObjectReaderImplList.of(type, null, 0);
+                    case "cn.hutool.core.lang.tree.Tree":
+                        return ObjectReaderImplMap.of(null, (Class<?>) rawType, 0L);
                 }
 
                 if (rawType == Optional.class) {


Test patch:
diff --git a/core/src/test/java/com/alibaba/fastjson2/issues_2300/Issue2375.java b/core/src/test/java/com/alibaba/fastjson2/issues_2300/Issue2375.java
new file mode 100644
index 000000000..1c7110768
--- /dev/null
+++ b/core/src/test/java/com/alibaba/fastjson2/issues_2300/Issue2375.java
@@ -0,0 +1,55 @@
+package com.alibaba.fastjson2.issues_2300;
+
+import cn.hutool.core.lang.tree.Tree;
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.TypeReference;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.json.JSONException;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.skyscreamer.jsonassert.JSONAssert;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author 张治保
+ * @since 2024/3/29
+ */
+public class Issue2375 {
+    @Test
+    void test() throws JSONException {
+        String jsonString = "{\"name\":\"name\",\"id\":\"1\",\"extra\":\"extra\"}";
+        Tree<String> tree = JSON.parseObject(jsonString, new TypeReference<Tree<String>>() {
+        });
+        JSONAssert.assertEquals(jsonString, JSON.toJSONString(tree), true);
+
+        Tree tree2 = JSON.parseObject(jsonString, Tree.class);
+        JSONAssert.assertEquals(jsonString, JSON.toJSONString(tree2), true);
+    }
+
+    @Test
+    void test2() throws JsonProcessingException {
+        String jsonString = "{\"treeList\":[{\"name\":\"name\",\"id\":\"1\",\"extra\":\"extra\"}]}";
+        DemoVO2 vo2 = JSON.parseObject(jsonString, DemoVO2.class);
+        List<Tree<String>> list = vo2.getTreeList();
+        DemoVO2 read = new ObjectMapper().readValue(jsonString, DemoVO2.class);
+        List<Tree<String>> list1 = read.getTreeList();
+        Assertions.assertEquals(list, list1);
+    }
+
+    private static class DemoVO2
+            implements Serializable {
+        private static final long serialVersionUID = 1L;
+        List<Tree<String>> treeList;
+
+        public List<Tree<String>> getTreeList() {
+            return treeList;
+        }
+
+        public void setTreeList(List<Tree<String>> treeList) {
+            this.treeList = treeList;
+        }
+    }
+}