Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/com/esotericsoftware/kryo/serializers/CachedFields.java
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,11 @@ private void addField (Field field, boolean asm, ArrayList<CachedField> fields,
}
}

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

if (removedFields.contains(field)) return;

Expand Down
13 changes: 12 additions & 1 deletion src/com/esotericsoftware/kryo/serializers/FieldSerializer.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import com.esotericsoftware.reflectasm.FieldAccess;

import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
Expand Down Expand Up @@ -350,15 +351,25 @@ public String toString () {

}

/** Indicates a field should be ignored when its declaring class is registered unless the {@link Kryo#getContext() context} has
* a value set for a key specified by at least one of the {@link Optional} annotations. */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Optionals {
Optional[] value();
}

/** Indicates a field should be ignored when its declaring class is registered unless the {@link Kryo#getContext() context} has
* a value set for the specified key. This can be useful when a field must be serialized for one purpose, but not for another.
* Eg, a class for a networked application could have a field that should not be serialized and sent to clients, but should be
* serialized when stored on the server.
* If a field has multiple of this annotation, then the field is serialized if at least one of the keys is present in the context.
* @author Nathan Sweet */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Repeatable(Optionals.class)
public @interface Optional {
public String value();
String value();
}

/** Used to annotate fields with a specific Kryo serializer.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -364,10 +364,35 @@ void testOptionalAnnotation () {
kryo.setRegistrationRequired(false);
kryo.setReferences(true);
roundTrip(82, new HasOptionalAnnotation());

kryo = new Kryo();
kryo.setRegistrationRequired(false);
kryo.setReferences(true);
kryo.getContext().put("smurf", null);
roundTrip(83, new HasOptionalAnnotation());

// To verify that more than one matching key is fine
kryo = new Kryo();
kryo.setRegistrationRequired(false);
kryo.setReferences(true);
kryo.getContext().put("smurf", null);
kryo.getContext().put("another smurf", null);
roundTrip(83, new HasOptionalAnnotation());

// To verify that additional keys do not matter
kryo = new Kryo();
kryo.setRegistrationRequired(false);
kryo.setReferences(true);
kryo.getContext().put("smurf", null);
kryo.getContext().put("another smurf", null);
kryo.getContext().put("has nothing to do with it", null);
roundTrip(83, new HasOptionalAnnotation());

// To verify that the order of Optional annotations does not matter
kryo = new Kryo();
kryo.setRegistrationRequired(false);
kryo.setReferences(true);
kryo.getContext().put("another smurf", null);
roundTrip(83, new HasOptionalAnnotation());
}

Expand Down Expand Up @@ -1026,7 +1051,7 @@ public boolean equals (Object obj) {
}

public static class HasOptionalAnnotation {
@Optional("smurf") int moo;
@Optional("smurf") @Optional("another smurf") int moo;

public boolean equals (Object obj) {
if (this == obj) return true;
Expand Down