This is an automated email from the ASF dual-hosted git repository.
chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory.git
The following commit(s) were added to refs/heads/main by this push:
new 6865924c8 fix(java): support inherited fields in xlang (#3838)
6865924c8 is described below
commit 6865924c883d98b92fafcddd1b9ee102517e42bc
Author: Shawn Yang <[email protected]>
AuthorDate: Mon Jul 13 17:42:52 2026 +0530
fix(java): support inherited fields in xlang (#3838)
## Why?
## What does this PR do?
## Related issues
Closes #3836
## AI Contribution Checklist
- [ ] Substantial AI assistance was used in this PR: `yes` / `no`
- [ ] If `yes`, I included a completed [AI Contribution
Checklist](https://github.com/apache/fory/blob/main/AI_POLICY.md#9-contributor-checklist-for-ai-assisted-prs)
in this PR description and the required `AI Usage Disclosure`.
- [ ] If `yes`, my PR description includes the required `ai_review`
summary and screenshot evidence or equivalent persisted links of the
final clean AI review results from both fresh reviewers described in
`AI_POLICY.md`, the Fory-guided reviewer and the independent general
reviewer, on the current PR diff or current HEAD after the latest code
changes.
## Does this PR introduce any user-facing change?
- [ ] Does this PR introduce any public API change?
- [ ] Does this PR introduce any binary protocol compatibility change?
## Benchmark
---
.../main/java/org/apache/fory/meta/TypeDef.java | 26 +++++++++++++++++-----
.../java/org/apache/fory/meta/TypeDefEncoder.java | 3 +--
.../org/apache/fory/xlang/MetaShareXlangTest.java | 22 ++++++++++++++++++
3 files changed, 43 insertions(+), 8 deletions(-)
diff --git a/java/fory-core/src/main/java/org/apache/fory/meta/TypeDef.java
b/java/fory-core/src/main/java/org/apache/fory/meta/TypeDef.java
index 5e8b33eac..bc1a26fca 100644
--- a/java/fory-core/src/main/java/org/apache/fory/meta/TypeDef.java
+++ b/java/fory-core/src/main/java/org/apache/fory/meta/TypeDef.java
@@ -367,8 +367,24 @@ public class TypeDef implements Serializable {
private List<Descriptor> buildDescriptors(
TypeResolver resolver, Class<?> cls, Collection<Descriptor>
fieldDescriptors) {
+ boolean isXlang = resolver.isCrossLanguage();
Map<String, Descriptor> descriptorsMap = new HashMap<>();
Map<Short, Descriptor> fieldIdToDescriptorMap = new HashMap<>();
+ Map<String, Descriptor> xlangNameDescriptors = null;
+
+ if (isXlang) {
+ xlangNameDescriptors = new HashMap<>();
+ // Xlang TypeDef flattens inherited fields and does not encode their
Java declaring class.
+ // Reuse the encoder's shadow/collision selection so name-based fields
bind by the same
+ // language-neutral identifier on both the schema and local descriptor
sides.
+ List<Descriptor> xlangDescriptors =
+ TypeDefEncoder.dropShadowedXlangNameFields(cls, new
ArrayList<>(fieldDescriptors));
+ for (Descriptor descriptor : xlangDescriptors) {
+ if (!descriptor.hasForyFieldId()) {
+ xlangNameDescriptors.put(descriptor.getSnakeCaseName(), descriptor);
+ }
+ }
+ }
for (Descriptor descriptor : fieldDescriptors) {
String fullName = descriptor.getDeclaringClass() + "." +
descriptor.getName();
@@ -390,7 +406,6 @@ public class TypeDef implements Serializable {
}
}
List<Descriptor> descriptors = new ArrayList<>(fieldsInfo.size());
- boolean isXlang = resolver.isCrossLanguage();
Collection<Descriptor> remoteDescriptors = null;
Map<String, Descriptor> remoteDescriptorsMap = null;
Map<Short, Descriptor> remoteFieldIdToDescriptorMap = null;
@@ -400,15 +415,14 @@ public class TypeDef implements Serializable {
Descriptor descriptor;
if (fieldInfo.hasFieldId()) {
descriptor = fieldIdToDescriptorMap.get(fieldInfo.getFieldId());
+ } else if (isXlang) {
+ descriptor =
+ xlangNameDescriptors.get(
+
StringUtils.lowerCamelToLowerUnderscore(fieldInfo.getFieldName()));
} else {
String fieldName = fieldInfo.getFieldName();
String definedClass = fieldInfo.getDefinedClass();
descriptor = descriptorsMap.get(definedClass + "." + fieldName);
- if (descriptor == null && isXlang) {
- descriptor =
- descriptorsMap.get(
- definedClass + "." +
StringUtils.lowerCamelToLowerUnderscore(fieldName));
- }
}
boolean remoteOnly = false;
if (descriptor == null) {
diff --git
a/java/fory-core/src/main/java/org/apache/fory/meta/TypeDefEncoder.java
b/java/fory-core/src/main/java/org/apache/fory/meta/TypeDefEncoder.java
index a5fb05147..d7abc0d58 100644
--- a/java/fory-core/src/main/java/org/apache/fory/meta/TypeDefEncoder.java
+++ b/java/fory-core/src/main/java/org/apache/fory/meta/TypeDefEncoder.java
@@ -75,8 +75,7 @@ class TypeDefEncoder {
resolver, type, buildFieldsInfoFromDescriptors(resolver, type,
descriptors));
}
- private static List<Descriptor> dropShadowedXlangNameFields(
- Class<?> type, List<Descriptor> descriptors) {
+ static List<Descriptor> dropShadowedXlangNameFields(Class<?> type,
List<Descriptor> descriptors) {
List<Descriptor> result = new ArrayList<>(descriptors.size());
Map<String, Integer> nameFieldIndex = new HashMap<>();
for (Descriptor descriptor : descriptors) {
diff --git
a/java/fory-core/src/test/java/org/apache/fory/xlang/MetaShareXlangTest.java
b/java/fory-core/src/test/java/org/apache/fory/xlang/MetaShareXlangTest.java
index 70c4e664d..966b2cc0d 100644
--- a/java/fory-core/src/test/java/org/apache/fory/xlang/MetaShareXlangTest.java
+++ b/java/fory-core/src/test/java/org/apache/fory/xlang/MetaShareXlangTest.java
@@ -23,11 +23,14 @@ import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertThrows;
import static org.testng.Assert.assertTrue;
+import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
import lombok.Data;
import org.apache.fory.Fory;
import org.apache.fory.ForyTestBase;
@@ -119,6 +122,25 @@ public class MetaShareXlangTest extends ForyTestBase {
Set<int[]> values;
}
+ abstract static class InheritedFieldParent {
+ public Map<String, BigDecimal> values = new ConcurrentHashMap<>();
+ }
+
+ static class InheritedFieldChild extends InheritedFieldParent {}
+
+ @Test
+ public void testInheritedField() {
+ for (boolean codegen : new boolean[] {false, true}) {
+ Fory fory = compatibleFory(InheritedFieldChild.class, codegen);
+ InheritedFieldChild value = new InheritedFieldChild();
+ value.values.put("one", BigDecimal.ONE);
+
+ InheritedFieldChild decoded = (InheritedFieldChild)
fory.deserialize(fory.serialize(value));
+
+ assertEquals(decoded.values, value.values);
+ }
+ }
+
@Test
public void testTopLevelListArrayCompatibleRead() {
Fory listFory = compatibleFory(DirectListField.class);
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]