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/fury.git


The following commit(s) were added to refs/heads/main by this push:
     new 895c6e1d feat(java): Add 'Expose' annotation to support "only 
de/serialize annotated fields" (#1751)
895c6e1d is described below

commit 895c6e1d2190879494ec9f733e1d5bcbcb26396f
Author: urlyy <[email protected]>
AuthorDate: Tue Jul 23 17:45:46 2024 +0800

    feat(java): Add 'Expose' annotation to support "only de/serialize annotated 
fields" (#1751)
    
    ## What does this PR do?
    Add `Expose` annotation to support "only de/serialize annotated fields"
    
    ## Related issues
    #1735
    
    ## Does this PR introduce any user-facing change?
    - [x] Does this PR introduce any public API change?
    - [ ] Does this PR introduce any binary protocol compatibility change?
    
    ## Benchmark
    N/A
---
 .../java/org/apache/fury/annotation/Expose.java    | 30 +++++++++++++++++
 .../main/java/org/apache/fury/type/Descriptor.java | 28 +++++++++++++---
 .../src/test/java/org/apache/fury/FuryTest.java    | 38 ++++++++++++++++++++++
 3 files changed, 92 insertions(+), 4 deletions(-)

diff --git 
a/java/fury-core/src/main/java/org/apache/fury/annotation/Expose.java 
b/java/fury-core/src/main/java/org/apache/fury/annotation/Expose.java
new file mode 100644
index 00000000..83a4e8be
--- /dev/null
+++ b/java/fury-core/src/main/java/org/apache/fury/annotation/Expose.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.fury.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/** Only fields with this annotation are permitted for de/serialization. */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface Expose {}
diff --git a/java/fury-core/src/main/java/org/apache/fury/type/Descriptor.java 
b/java/fury-core/src/main/java/org/apache/fury/type/Descriptor.java
index ade3bbaf..7b69d024 100644
--- a/java/fury-core/src/main/java/org/apache/fury/type/Descriptor.java
+++ b/java/fury-core/src/main/java/org/apache/fury/type/Descriptor.java
@@ -42,6 +42,7 @@ import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.ForkJoinPool;
 import java.util.concurrent.atomic.AtomicBoolean;
+import org.apache.fury.annotation.Expose;
 import org.apache.fury.annotation.Ignore;
 import org.apache.fury.annotation.Internal;
 import org.apache.fury.collection.Tuple2;
@@ -370,14 +371,33 @@ public class Descriptor {
     }
     do {
       Field[] fields = clazz.getDeclaredFields();
+      boolean haveExpose = false, haveIgnore = false;
       for (Field field : fields) {
         warmField(clz, field, compilationService);
+        if (field.isAnnotationPresent(Expose.class)) {
+          haveExpose = true;
+        }
+        if (field.isAnnotationPresent(Ignore.class)) {
+          haveIgnore = true;
+        }
+        if (haveExpose && haveIgnore) {
+          throw new RuntimeException(
+              "Fields of a Class are not allowed to have both the Ignore and 
Expose annotations simultaneously.");
+        }
+      }
+      for (Field field : fields) {
         int modifiers = field.getModifiers();
         // final and non-private field validation left to {@link isBean(clz)}
-        if (!Modifier.isTransient(modifiers)
-            && !Modifier.isStatic(modifiers)
-            && !field.isAnnotationPresent(Ignore.class)) {
-          descriptorMap.put(field, new Descriptor(field, null));
+        if (!Modifier.isTransient(modifiers) && !Modifier.isStatic(modifiers)) 
{
+          if (haveExpose) {
+            if (field.isAnnotationPresent(Expose.class)) {
+              descriptorMap.put(field, new Descriptor(field, null));
+            }
+          } else {
+            if (!field.isAnnotationPresent(Ignore.class)) {
+              descriptorMap.put(field, new Descriptor(field, null));
+            }
+          }
         }
       }
       if (clazz == clz) {
diff --git a/java/fury-core/src/test/java/org/apache/fury/FuryTest.java 
b/java/fury-core/src/test/java/org/apache/fury/FuryTest.java
index 072ff9f6..032c609e 100644
--- a/java/fury-core/src/test/java/org/apache/fury/FuryTest.java
+++ b/java/fury-core/src/test/java/org/apache/fury/FuryTest.java
@@ -52,6 +52,7 @@ import java.util.WeakHashMap;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
+import org.apache.fury.annotation.Expose;
 import org.apache.fury.annotation.Ignore;
 import org.apache.fury.builder.Generated;
 import org.apache.fury.config.FuryBuilder;
@@ -437,6 +438,43 @@ public class FuryTest extends FuryTestBase {
     assertEquals(3, o.f3);
   }
 
+  @Data
+  @AllArgsConstructor
+  private static class ExposeFields {
+    @Expose int f1;
+    @Expose long f2;
+    long f3;
+    @Expose ImmutableMap<String, Integer> map1;
+    ImmutableMap<String, Integer> map2;
+  }
+
+  @Test
+  public void testExposeFields() {
+    Fury fury = Fury.builder().requireClassRegistration(false).build();
+    ImmutableMap<String, Integer> map1 = ImmutableMap.of("1", 1);
+    ImmutableMap<String, Integer> map2 = ImmutableMap.of("2", 2);
+    ExposeFields o = serDe(fury, new ExposeFields(1, 2, 3, map1, map2));
+    assertEquals(1, o.f1);
+    assertEquals(2, o.f2);
+    assertEquals(0, o.f3);
+    assertEquals(o.map1, map1);
+    assertNull(o.map2);
+  }
+
+  @Data
+  @AllArgsConstructor
+  private static class ExposeFields2 {
+    @Expose int f1;
+    @Ignore long f2;
+    long f3;
+  }
+
+  @Test
+  public void testExposeFields2() {
+    Fury fury = Fury.builder().requireClassRegistration(false).build();
+    assertThrows(RuntimeException.class, () -> serDe(fury, new 
ExposeFields2(1, 2, 3)));
+  }
+
   @Test(timeOut = 60_000)
   public void testClassGC() {
     WeakHashMap<Object, Boolean> map = new WeakHashMap<>();


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

Reply via email to