This is an automated email from the ASF dual-hosted git repository. chaokunyang pushed a commit to branch releases-0.12 in repository https://gitbox.apache.org/repos/asf/fory.git
commit a4e4c5f6ce7fb0c0632525bd650dbaaea0223112 Author: Shawn Yang <[email protected]> AuthorDate: Thu Aug 14 19:08:03 2025 +0800 fix(java): fix row encoder for private struct (#2469) ## What does this PR do? <!-- Describe the purpose of this PR. --> ## Related issues Closes #2439 ## Does this PR introduce any user-facing change? <!-- If any user-facing interface changes, please [open an issue](https://github.com/apache/fory/issues/new/choose) describing the need to do so and update the document if necessary. --> - [ ] Does this PR introduce any public API change? - [ ] Does this PR introduce any binary protocol compatibility change? ## Benchmark <!-- When the PR has an impact on performance (if you don't know whether the PR will have an impact on performance, you can submit the PR first, and if it will have impact on performance, the code reviewer will explain it), be sure to attach a benchmark data here. --> --- .../main/java/org/apache/fory/type/TypeUtils.java | 63 ++++++++++------------ .../fory/format/encoder/RowEncoderBuilder.java | 2 +- .../apache/fory/format/encoder/RowEncoderTest.java | 17 ++++++ 3 files changed, 47 insertions(+), 35 deletions(-) diff --git a/java/fory-core/src/main/java/org/apache/fory/type/TypeUtils.java b/java/fory-core/src/main/java/org/apache/fory/type/TypeUtils.java index a4af2479f..5d35b5b5c 100644 --- a/java/fory-core/src/main/java/org/apache/fory/type/TypeUtils.java +++ b/java/fory-core/src/main/java/org/apache/fory/type/TypeUtils.java @@ -619,43 +619,38 @@ public class TypeUtils { || ctx.getCustomTypeRegistry().isExtraSupportedType(typeRef)) { return false; } - // since we need to access class in generated code in our package, the class must be public // if ReflectionUtils.hasNoArgConstructor(cls) return false, we use Unsafe to create object. - if (Modifier.isPublic(cls.getModifiers())) { - // bean class can be static nested class, but can't be not a non-static inner class - if (cls.getEnclosingClass() != null && !Modifier.isStatic(cls.getModifiers())) { - return false; - } - TypeResolutionContext newTypePath = ctx.appendTypePath(typeRef); - if (cls == Object.class) { - // return false for typeToken that point to un-specialized generic type. - return false; - } - boolean maybe = - !SUPPORTED_TYPES.contains(typeRef) - && !typeRef.isArray() - && !cls.isEnum() - && !ITERABLE_TYPE.isSupertypeOf(typeRef) - && !MAP_TYPE.isSupertypeOf(typeRef); - if (maybe) { - for (Descriptor d : Descriptor.getDescriptors(cls)) { - TypeRef<?> t = d.getTypeRef(); - // do field modifiers and getter/setter validation here, not in getDescriptors. - // If Modifier.isFinal(d.getModifiers()), use reflection - // private field that doesn't have getter/setter will be handled by reflection. - TypeRef<?> replacementType = - ctx.getCustomTypeRegistry().replacementTypeFor(cls, t.getRawType()); - if (replacementType != null) { - t = replacementType; - } - if (!isSupported(t, newTypePath)) { - return false; - } + // bean class can be static nested class, but can't be not a non-static inner class + if (cls.getEnclosingClass() != null && !Modifier.isStatic(cls.getModifiers())) { + return false; + } + TypeResolutionContext newTypePath = ctx.appendTypePath(typeRef); + if (cls == Object.class) { + // return false for typeToken that point to un-specialized generic type. + return false; + } + boolean maybe = + !SUPPORTED_TYPES.contains(typeRef) + && !typeRef.isArray() + && !cls.isEnum() + && !ITERABLE_TYPE.isSupertypeOf(typeRef) + && !MAP_TYPE.isSupertypeOf(typeRef); + if (maybe) { + for (Descriptor d : Descriptor.getDescriptors(cls)) { + TypeRef<?> t = d.getTypeRef(); + // do field modifiers and getter/setter validation here, not in getDescriptors. + // If Modifier.isFinal(d.getModifiers()), use reflection + // private field that doesn't have getter/setter will be handled by reflection. + TypeRef<?> replacementType = + ctx.getCustomTypeRegistry().replacementTypeFor(cls, t.getRawType()); + if (replacementType != null) { + t = replacementType; + } + if (!isSupported(t, newTypePath)) { + return false; } - return true; - } else { - return false; } + return true; } else { return false; } 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 f8c16a38c..45f65fff9 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 @@ -184,7 +184,7 @@ public class RowEncoderBuilder extends BaseBinaryEncoderBuilder { @Override public Expression buildEncodeExpression() { Reference inputObject = new Reference(ROOT_OBJECT_NAME, TypeUtils.OBJECT_TYPE, false); - Expression bean = new Expression.Cast(inputObject, beanType, ctx.newName(beanClass)); + Expression bean = tryCastIfPublic(inputObject, beanType); Reference writer = new Reference(ROOT_ROW_WRITER_NAME, rowWriterTypeToken, false); Reference schemaExpr = new Reference(SCHEMA_NAME, schemaTypeToken, false); diff --git a/java/fory-format/src/test/java/org/apache/fory/format/encoder/RowEncoderTest.java b/java/fory-format/src/test/java/org/apache/fory/format/encoder/RowEncoderTest.java index dd6832e9a..484296456 100644 --- a/java/fory-format/src/test/java/org/apache/fory/format/encoder/RowEncoderTest.java +++ b/java/fory-format/src/test/java/org/apache/fory/format/encoder/RowEncoderTest.java @@ -19,6 +19,7 @@ package org.apache.fory.format.encoder; +import static org.apache.fory.collection.Collections.ofHashMap; import static org.apache.fory.format.encoder.CodecBuilderTest.testStreamingEncode; import com.google.common.collect.ImmutableMap; @@ -101,4 +102,20 @@ public class RowEncoderTest { Foo deserializedFoo = encoder.fromRow(row); Assert.assertEquals(foo, deserializedFoo); } + + private static class PrivateStruct { + java.util.Map<Long, Long> f1; + java.util.Map<String, String> f2; + } + + @Test + public void testPrivateBean() { + RowEncoder<PrivateStruct> encoder = Encoders.bean(PrivateStruct.class); + PrivateStruct s = new PrivateStruct(); + s.f1 = ofHashMap(10L, 100L); + s.f2 = ofHashMap("k", "v"); + PrivateStruct s1 = encoder.decode(encoder.encode(s)); + Assert.assertEquals(s1.f1, s.f1); + Assert.assertEquals(s1.f2, s.f2); + } } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
