Repository: alibaba/fastjson2
Pull request #3244 (2025-01-01 10:24:23)

fix seeAlso
### 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/ObjectReaderSeeAlso.java b/core/src/main/java/com/alibaba/fastjson2/reader/ObjectReaderSeeAlso.java
index d2fa9b455..bc95a2f83 100644
--- a/core/src/main/java/com/alibaba/fastjson2/reader/ObjectReaderSeeAlso.java
+++ b/core/src/main/java/com/alibaba/fastjson2/reader/ObjectReaderSeeAlso.java
@@ -7,6 +7,8 @@ import com.alibaba.fastjson2.util.Fnv;
 
 import java.lang.reflect.Type;
 import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.Map;
 import java.util.function.Function;
 import java.util.function.Supplier;
 
@@ -139,6 +141,7 @@ final class ObjectReaderSeeAlso<T>
             }
         }
 
+        Map<Long, Object> fieldValues = null;
         for (int i = 0; ; i++) {
             if (jsonReader.nextIfObjectEnd()) {
                 if (object == null) {
@@ -246,7 +249,22 @@ final class ObjectReaderSeeAlso<T>
                 continue;
             }
 
-            fieldReader.readFieldValue(jsonReader, object);
+            if (object == null) {
+                Object fieldValue = fieldReader.readFieldValue(jsonReader);
+                if (fieldValues == null) {
+                    fieldValues = new LinkedHashMap<>();
+                }
+                fieldValues.put(hash, fieldValue);
+            } else {
+                fieldReader.readFieldValue(jsonReader, object);
+            }
+        }
+
+        if (fieldValues != null) {
+            for (Map.Entry<Long, Object> entry : fieldValues.entrySet()) {
+                FieldReader fieldReader = getFieldReader(entry.getKey());
+                fieldReader.accept(object, entry.getValue());
+            }
         }
 
         jsonReader.nextIfComma();
diff --git a/core/src/main/java/com/alibaba/fastjson2/writer/ObjectWriterCreator.java b/core/src/main/java/com/alibaba/fastjson2/writer/ObjectWriterCreator.java
index 713f753f7..d2425f209 100644
--- a/core/src/main/java/com/alibaba/fastjson2/writer/ObjectWriterCreator.java
+++ b/core/src/main/java/com/alibaba/fastjson2/writer/ObjectWriterCreator.java
@@ -175,6 +175,9 @@ public class ObjectWriterCreator {
                 }
             }
         }
+        if (fieldInfo.ordinal == 0 && fieldName.equals(beanInfo.typeKey)) {
+            fieldInfo.ordinal = -1;
+        }
 
         if (beanInfo.includes != null && beanInfo.includes.length > 0) {
             boolean match = false;


Test patch:
diff --git a/core/src/test/java/com/alibaba/fastjson2/issues_2900/Issue2987.java b/core/src/test/java/com/alibaba/fastjson2/issues_2900/Issue2987.java
new file mode 100644
index 000000000..2e6a833b8
--- /dev/null
+++ b/core/src/test/java/com/alibaba/fastjson2/issues_2900/Issue2987.java
@@ -0,0 +1,58 @@
+package com.alibaba.fastjson2.issues_2900;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.annotation.JSONType;
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class Issue2987 {
+    @Test
+    public void test() {
+        MyFile myFile = new MyFile();
+        myFile.type = "file";
+        myFile.name = "my_file.txt";
+        myFile.data = "Some content ...";
+
+        MyDirectory myDirectory = new MyDirectory();
+        myDirectory.type = "directory";
+        myDirectory.name = "My directory";
+        myDirectory.items = Arrays.asList(myFile);
+
+        String json = JSON.toJSONString(myDirectory);
+        System.out.println(json);
+        {
+            MyDirectory object = JSON.parseObject(json, MyDirectory.class);
+            assertNotNull(object);
+        }
+        {
+            MyNode object = JSON.parseObject(json, MyNode.class);
+            assertTrue(object instanceof MyDirectory);
+        }
+    }
+
+    @JSONType(
+            typeKey = "type",
+            seeAlso = {MyDirectory.class, MyFile.class}
+    )
+    abstract class MyNode {
+        public String type;
+        public String name;
+    }
+
+    @JSONType(typeName = "file")
+    class MyFile
+            extends MyNode {
+        public String data;
+    }
+
+    @JSONType(typeName = "directory")
+    class MyDirectory
+            extends MyNode {
+        public List<MyNode> items;
+    }
+}