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 875010df fix(java): fix row encoder synthesized interface 
lazy-decoding of Optional (#2320)
875010df is described below

commit 875010df24a69c76771b2d4c358f8defb8a53f82
Author: Steven Schlansker <[email protected]>
AuthorDate: Mon Jun 9 20:22:12 2025 -0700

    fix(java): fix row encoder synthesized interface lazy-decoding of Optional 
(#2320)
    
    ## What does this PR do?
    
    fix incorrect handling of Optional types nested inside of synthesized
    bean interfaces
    
    If we build another 0.11.0 rc, it would be nice to include this fix if
    possible.
---
 .../fory/format/encoder/RowEncoderBuilder.java      | 15 +++++++++++----
 .../fory/format/encoder/ImplementInterfaceTest.java | 21 +++++++++++++++++++--
 2 files changed, 30 insertions(+), 6 deletions(-)

diff --git 
a/java/fory-format/src/main/java/org/apache/fory/format/encoder/RowEncoderBuilder.java
 
b/java/fory-format/src/main/java/org/apache/fory/format/encoder/RowEncoderBuilder.java
index a1026052..ac9118c8 100644
--- 
a/java/fory-format/src/main/java/org/apache/fory/format/encoder/RowEncoderBuilder.java
+++ 
b/java/fory-format/src/main/java/org/apache/fory/format/encoder/RowEncoderBuilder.java
@@ -340,14 +340,21 @@ public class RowEncoderBuilder extends 
BaseBinaryEncoderBuilder {
         getterImpl = new Expression.Return(decodeValue);
       } else {
         String fieldName = "f" + i + "_" + d.getName();
-        implClass.addField(
-            false, ctx.type(fieldType.getRawType()), fieldName, 
nullValue(fieldType));
+        Class<?> rawFieldType = fieldType.getRawType();
+        implClass.addField(false, ctx.type(rawFieldType), fieldName, 
nullValue(fieldType));
 
         Expression fieldRef = new Expression.Reference(fieldName, fieldType, 
true);
         Expression storeValue =
             new Expression.SetField(new Expression.Reference("this"), 
fieldName, decodeValue);
-        Expression loadIfFieldIsNull =
-            new Expression.If(new Expression.IsNull(fieldRef), storeValue);
+        Expression shouldLoad;
+        if (rawFieldType == Optional.class) {
+          shouldLoad =
+              new Expression.Not(
+                  Expression.Invoke.inlineInvoke(fieldRef, "isPresent", 
TypeUtils.BOOLEAN_TYPE));
+        } else {
+          shouldLoad = new Expression.IsNull(fieldRef);
+        }
+        Expression loadIfFieldIsNull = new Expression.If(shouldLoad, 
storeValue);
         Expression assigner;
 
         if (d.isNullable()) {
diff --git 
a/java/fory-format/src/test/java/org/apache/fory/format/encoder/ImplementInterfaceTest.java
 
b/java/fory-format/src/test/java/org/apache/fory/format/encoder/ImplementInterfaceTest.java
index 70af5f1b..40fec4e6 100644
--- 
a/java/fory-format/src/test/java/org/apache/fory/format/encoder/ImplementInterfaceTest.java
+++ 
b/java/fory-format/src/test/java/org/apache/fory/format/encoder/ImplementInterfaceTest.java
@@ -135,15 +135,21 @@ public class ImplementInterfaceTest {
   }
 
   static class OptionalTypeImpl implements OptionalType {
+    private final Optional<String> f1;
+
+    OptionalTypeImpl(final Optional<String> f1) {
+      this.f1 = f1;
+    }
+
     @Override
     public Optional<String> f1() {
-      return null;
+      return f1;
     }
   }
 
   @Test
   public void testNullOptional() {
-    final OptionalType bean1 = new OptionalTypeImpl();
+    final OptionalType bean1 = new OptionalTypeImpl(null);
     final RowEncoder<OptionalType> encoder = Encoders.bean(OptionalType.class);
     final BinaryRow row = encoder.toRow(bean1);
     final MemoryBuffer buffer = MemoryUtils.wrap(row.toBytes());
@@ -151,4 +157,15 @@ public class ImplementInterfaceTest {
     final OptionalType deserializedBean = encoder.fromRow(row);
     Assert.assertEquals(deserializedBean.f1(), Optional.empty());
   }
+
+  @Test
+  public void testPresentOptional() {
+    final OptionalType bean1 = new OptionalTypeImpl(Optional.of("42"));
+    final RowEncoder<OptionalType> encoder = Encoders.bean(OptionalType.class);
+    final BinaryRow row = encoder.toRow(bean1);
+    final MemoryBuffer buffer = MemoryUtils.wrap(row.toBytes());
+    row.pointTo(buffer, 0, buffer.size());
+    final OptionalType deserializedBean = encoder.fromRow(row);
+    Assert.assertEquals(deserializedBean.f1(), Optional.of("42"));
+  }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to