Skip to content

Commit 680bda7

Browse files
committed
Make Optional annotation repeatable
1 parent 178ede5 commit 680bda7

3 files changed

Lines changed: 41 additions & 4 deletions

File tree

src/com/esotericsoftware/kryo/serializers/CachedFields.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,11 @@ private void addField (Field field, boolean asm, ArrayList<CachedField> fields,
127127
}
128128
}
129129

130-
Optional optional = field.getAnnotation(Optional.class);
131-
if (optional != null && !serializer.kryo.getContext().containsKey(optional.value())) return;
130+
Optional[] optionals = field.getAnnotationsByType(Optional.class);
131+
if (optionals.length > 0 && Arrays.stream(optionals).noneMatch(
132+
optional -> serializer.kryo.getContext().containsKey(optional.value()))) {
133+
return;
134+
}
132135

133136
if (removedFields.contains(field)) return;
134137

src/com/esotericsoftware/kryo/serializers/FieldSerializer.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,15 +350,24 @@ public String toString () {
350350

351351
}
352352

353+
/** Indicates a field should be ignored when its declaring class is registered unless the {@link Kryo#getContext() context} has
354+
* a value set for a key specified by at least one of the {@link Optional} annotations. */
355+
@Retention(RetentionPolicy.RUNTIME)
356+
@Target(ElementType.FIELD)
357+
public @interface Optionals {
358+
Optional[] value();
359+
}
360+
353361
/** Indicates a field should be ignored when its declaring class is registered unless the {@link Kryo#getContext() context} has
354362
* a value set for the specified key. This can be useful when a field must be serialized for one purpose, but not for another.
355363
* Eg, a class for a networked application could have a field that should not be serialized and sent to clients, but should be
356364
* serialized when stored on the server.
357365
* @author Nathan Sweet */
358366
@Retention(RetentionPolicy.RUNTIME)
359367
@Target(ElementType.FIELD)
368+
@Repeatable(Optionals.class)
360369
public @interface Optional {
361-
public String value();
370+
String value();
362371
}
363372

364373
/** Used to annotate fields with a specific Kryo serializer.

test/com/esotericsoftware/kryo/serializers/FieldSerializerTest.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,10 +364,35 @@ void testOptionalAnnotation () {
364364
kryo.setRegistrationRequired(false);
365365
kryo.setReferences(true);
366366
roundTrip(82, new HasOptionalAnnotation());
367+
368+
kryo = new Kryo();
369+
kryo.setRegistrationRequired(false);
370+
kryo.setReferences(true);
371+
kryo.getContext().put("smurf", null);
372+
roundTrip(83, new HasOptionalAnnotation());
373+
374+
// To verify that more than one matching key is fine
375+
kryo = new Kryo();
376+
kryo.setRegistrationRequired(false);
377+
kryo.setReferences(true);
378+
kryo.getContext().put("smurf", null);
379+
kryo.getContext().put("another smurf", null);
380+
roundTrip(83, new HasOptionalAnnotation());
381+
382+
// To verify that additional keys do not matter
367383
kryo = new Kryo();
368384
kryo.setRegistrationRequired(false);
369385
kryo.setReferences(true);
370386
kryo.getContext().put("smurf", null);
387+
kryo.getContext().put("another smurf", null);
388+
kryo.getContext().put("has nothing to do with it", null);
389+
roundTrip(83, new HasOptionalAnnotation());
390+
391+
// To verify that the order of Optional annotations does not matter
392+
kryo = new Kryo();
393+
kryo.setRegistrationRequired(false);
394+
kryo.setReferences(true);
395+
kryo.getContext().put("another smurf", null);
371396
roundTrip(83, new HasOptionalAnnotation());
372397
}
373398

@@ -1026,7 +1051,7 @@ public boolean equals (Object obj) {
10261051
}
10271052

10281053
public static class HasOptionalAnnotation {
1029-
@Optional("smurf") int moo;
1054+
@Optional("smurf") @Optional("another smurf") int moo;
10301055

10311056
public boolean equals (Object obj) {
10321057
if (this == obj) return true;

0 commit comments

Comments
 (0)