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]