Skip to content

Commit 4571b65

Browse files
committed
Transient properties and annotation serialization
1 parent 4f7b02c commit 4571b65

File tree

6 files changed

+525
-72
lines changed

6 files changed

+525
-72
lines changed

src/main/java/dev/lukebemish/codecextras/structured/reflective/BuiltInReflectiveStructureCreator.java

Lines changed: 272 additions & 61 deletions
Large diffs are not rendered by default.

src/main/java/dev/lukebemish/codecextras/structured/reflective/SerializedProperty.java

Lines changed: 0 additions & 10 deletions
This file was deleted.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package dev.lukebemish.codecextras.structured.reflective.annotations;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
8+
@Target({ElementType.PARAMETER})
9+
@Retention(RetentionPolicy.RUNTIME)
10+
public @interface SerializedProperty {
11+
String value();
12+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package dev.lukebemish.codecextras.structured.reflective.annotations;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
8+
@Target({ElementType.METHOD})
9+
@Retention(RetentionPolicy.RUNTIME)
10+
public @interface Transient {
11+
}

src/main/java/module-info.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232

3333
exports dev.lukebemish.codecextras.structured;
3434
exports dev.lukebemish.codecextras.structured.reflective;
35+
exports dev.lukebemish.codecextras.structured.reflective.annotations;
3536
exports dev.lukebemish.codecextras.structured.schema;
3637

3738
exports dev.lukebemish.codecextras.types;

src/test/java/dev/lukebemish/codecextras/test/structured/reflective/TestReflective.java

Lines changed: 229 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,22 @@
55
import dev.lukebemish.codecextras.structured.CodecInterpreter;
66
import dev.lukebemish.codecextras.structured.Structure;
77
import dev.lukebemish.codecextras.structured.reflective.ReflectiveStructureCreator;
8+
import dev.lukebemish.codecextras.structured.reflective.annotations.SerializedProperty;
9+
import dev.lukebemish.codecextras.structured.reflective.annotations.Transient;
810
import dev.lukebemish.codecextras.test.CodecAssertions;
11+
import java.lang.annotation.Retention;
12+
import java.lang.annotation.RetentionPolicy;
913
import java.util.LinkedHashSet;
1014
import java.util.List;
15+
import java.util.Objects;
1116
import java.util.Optional;
1217
import java.util.OptionalInt;
1318
import java.util.SequencedSet;
1419
import org.jspecify.annotations.Nullable;
1520
import org.junit.jupiter.api.Test;
1621

1722
public class TestReflective {
18-
public record TestRecord(int a, String b, TestEnum c, OptionalInt d, Optional<String> e, @Nullable String f, SequencedSet<Integer> g) {
23+
public record TestRecord(long a, String b, TestEnum c, OptionalInt d, Optional<String> e, @Nullable String f, SequencedSet<Integer> g) {
1924
private static final Structure<TestRecord> STRUCTURE = ReflectiveStructureCreator.create(TestRecord.class);
2025
}
2126

@@ -25,6 +30,120 @@ public enum TestEnum {
2530
C
2631
}
2732

33+
public static class TestNoArgCtor {
34+
public int a;
35+
private @Nullable String b;
36+
37+
public @Nullable String getB() {
38+
return this.b;
39+
}
40+
41+
public void setB(String b) {
42+
this.b = b;
43+
}
44+
45+
@Override
46+
public boolean equals(Object object) {
47+
if (this == object) return true;
48+
if (!(object instanceof TestNoArgCtor that)) return false;
49+
return a == that.a && Objects.equals(b, that.b);
50+
}
51+
52+
@Override
53+
public int hashCode() {
54+
return Objects.hash(a, b);
55+
}
56+
57+
@Override
58+
public String toString() {
59+
return "TestNoArgCtor{" +
60+
"a=" + a +
61+
", b='" + b + '\'' +
62+
'}';
63+
}
64+
}
65+
66+
public static class TestCtor {
67+
public final int a;
68+
private final String b;
69+
70+
public String getB() {
71+
return this.b;
72+
}
73+
74+
public TestCtor(
75+
@SerializedProperty("a") int a,
76+
@SerializedProperty("b") String b
77+
) {
78+
this.a = a;
79+
this.b = b;
80+
}
81+
82+
@Override
83+
public boolean equals(Object object) {
84+
if (this == object) return true;
85+
if (!(object instanceof TestCtor testCtor)) return false;
86+
return a == testCtor.a && Objects.equals(b, testCtor.b);
87+
}
88+
89+
@Override
90+
public int hashCode() {
91+
return Objects.hash(a, b);
92+
}
93+
94+
@Override
95+
public String toString() {
96+
return "TestCtor{" +
97+
"a=" + a +
98+
", b='" + b + '\'' +
99+
'}';
100+
}
101+
}
102+
103+
public static class TestAnnotations {
104+
public long a;
105+
public transient boolean b;
106+
107+
private boolean c;
108+
@Transient
109+
public boolean getC() {
110+
return this.c;
111+
}
112+
public void setC(boolean c) {
113+
this.c = c;
114+
}
115+
116+
private boolean d;
117+
public boolean isD() {
118+
return this.d;
119+
}
120+
public void setD(boolean d) {
121+
this.d = d;
122+
}
123+
124+
@Override
125+
public boolean equals(Object object) {
126+
if (this == object) return true;
127+
if (!(object instanceof TestAnnotations that)) return false;
128+
return a == that.a && b == that.b && c == that.c && d == that.d;
129+
}
130+
131+
@Override
132+
public int hashCode() {
133+
return Objects.hash(a, b, c, d);
134+
}
135+
136+
@Override
137+
public String toString() {
138+
return "TestAnnotations{" +
139+
"a=" + a +
140+
", b=" + b +
141+
", c=" + c +
142+
", d=" + d +
143+
'}';
144+
}
145+
}
146+
28147
public record TestRecursive(String name, List<TestRecursive> list) {}
29148

30149
private static final Codec<TestRecord> CODEC = CodecInterpreter.create().interpret(TestRecord.STRUCTURE).getOrThrow();
@@ -34,6 +153,11 @@ public record TestRecursive(String name, List<TestRecursive> list) {}
34153

35154
private static final Codec<TestRecursive> RECURSIVE_CODEC = CodecInterpreter.create().interpret(ReflectiveStructureCreator.create(TestRecursive.class)).getOrThrow();
36155

156+
private static final Codec<TestCtor> CTOR_CODEC = CodecInterpreter.create().interpret(ReflectiveStructureCreator.create(TestCtor.class)).getOrThrow();
157+
private static final Codec<TestNoArgCtor> NO_ARG_CTOR_CODEC = CodecInterpreter.create().interpret(ReflectiveStructureCreator.create(TestNoArgCtor.class)).getOrThrow();
158+
159+
private static final Codec<TestAnnotations> ANNOTATIONS_CODEC = CodecInterpreter.create().interpret(ReflectiveStructureCreator.create(TestAnnotations.class)).getOrThrow();
160+
37161
private final String json = """
38162
{
39163
"a": 1,
@@ -74,11 +198,36 @@ public record TestRecursive(String name, List<TestRecursive> list) {}
74198
]
75199
}""";
76200

201+
private final String ctorJson = """
202+
{
203+
"a": 1,
204+
"b": "test"
205+
}""";
206+
207+
private final String annotationsJson = """
208+
{
209+
"a": 1,
210+
"d": true
211+
}""";
212+
77213
private final TestRecord object = new TestRecord(1, "test", TestEnum.A, OptionalInt.of(2), Optional.of("test"), null, new LinkedHashSet<>(List.of(1, 2, 3)));
78214
private final TestRecord[] array = new TestRecord[] { object };
79215
private final int[] primitiveArray = new int[] { 1, 2, 3 };
80216
private final TestRecursive recursive = new TestRecursive("test1", List.of(new TestRecursive("test2", List.of()), new TestRecursive("test3", List.of())));
81217

218+
private final TestNoArgCtor noArgCtor = new TestNoArgCtor();
219+
{
220+
noArgCtor.a = 1;
221+
noArgCtor.setB("test");
222+
}
223+
private final TestCtor ctor = new TestCtor(1, "test");
224+
225+
private final TestAnnotations annotations = new TestAnnotations();
226+
{
227+
annotations.a = 1;
228+
annotations.setD(true);
229+
}
230+
82231
@Test
83232
void testDecoding() {
84233
CodecAssertions.assertDecodes(JsonOps.INSTANCE, json, object, CODEC);
@@ -118,4 +267,83 @@ void testDecodingRecursive() {
118267
void testEncodingRecursive() {
119268
CodecAssertions.assertEncodes(JsonOps.INSTANCE, recursive, recursiveJson, RECURSIVE_CODEC);
120269
}
270+
271+
@Test
272+
void testDecodingCtor() {
273+
CodecAssertions.assertDecodes(JsonOps.INSTANCE, ctorJson, ctor, CTOR_CODEC);
274+
}
275+
276+
@Test
277+
void testEncodingCtor() {
278+
CodecAssertions.assertEncodes(JsonOps.INSTANCE, ctor, ctorJson, CTOR_CODEC);
279+
}
280+
281+
@Test
282+
void testDecodingNoArgCtor() {
283+
CodecAssertions.assertDecodes(JsonOps.INSTANCE, ctorJson, noArgCtor, NO_ARG_CTOR_CODEC);
284+
}
285+
286+
@Test
287+
void testEncodingNoArgCtor() {
288+
CodecAssertions.assertEncodes(JsonOps.INSTANCE, noArgCtor, ctorJson, NO_ARG_CTOR_CODEC);
289+
}
290+
291+
@Test
292+
void testDecodingAnnotations() {
293+
CodecAssertions.assertDecodes(JsonOps.INSTANCE, annotationsJson, annotations, ANNOTATIONS_CODEC);
294+
}
295+
296+
@Test
297+
void testEncodingAnnotations() {
298+
CodecAssertions.assertEncodes(JsonOps.INSTANCE, annotations, annotationsJson, ANNOTATIONS_CODEC);
299+
}
300+
301+
@Retention(RetentionPolicy.RUNTIME)
302+
public @interface TestAnnotation {
303+
String a();
304+
long b();
305+
String[] c();
306+
long[] d();
307+
Nested e();
308+
Nested[] f();
309+
310+
@interface Nested {
311+
long a();
312+
}
313+
}
314+
private final String testAnnotationJson = """
315+
{
316+
"a": "test",
317+
"b": 1,
318+
"c": ["test1", "test2"],
319+
"d": [1, 2],
320+
"e": {"a": 1},
321+
"f": [{"a": 1}, {"a": 2}]
322+
}""";
323+
private final TestAnnotation testAnnotation = new Object() {
324+
@TestAnnotation(
325+
a = "test",
326+
b = 1,
327+
c = {"test1", "test2"},
328+
d = {1, 2},
329+
e = @TestAnnotation.Nested(a = 1),
330+
f = {@TestAnnotation.Nested(a = 1), @TestAnnotation.Nested(a = 2)}
331+
)
332+
static class Source {
333+
334+
}
335+
336+
final TestAnnotation annotation = Objects.requireNonNull(Source.class.getAnnotation(TestAnnotation.class));
337+
}.annotation;
338+
private static final Codec<TestAnnotation> TEST_ANNOTATION_CODEC = CodecInterpreter.create().interpret(ReflectiveStructureCreator.create(TestAnnotation.class)).getOrThrow();
339+
340+
@Test
341+
void testDecodingTestAnnotation() {
342+
CodecAssertions.assertDecodes(JsonOps.INSTANCE, testAnnotationJson, testAnnotation, TEST_ANNOTATION_CODEC);
343+
}
344+
345+
@Test
346+
void testEncodingTestAnnotation() {
347+
CodecAssertions.assertEncodes(JsonOps.INSTANCE, testAnnotation, testAnnotationJson, TEST_ANNOTATION_CODEC);
348+
}
121349
}

0 commit comments

Comments
 (0)