ProtoFeature.java
package net.morimekta.proto.jackson;
import com.fasterxml.jackson.databind.DeserializationConfig;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
/**
* Providence specific features or attributes used to configure
* serialization further. These are technically 'attributes' on
* the serialization config, but is used are simple feature
* flags.
*/
public enum ProtoFeature {
/**
* Fail when encountering an enum value (from string) that is unknown.
*/
FAIL_ON_UNKNOWN_ENUM(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, true),
/**
* Fail when encountering an unknown field on a message.
*/
FAIL_ON_UNKNOWN_FIELD(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false),
/**
* Fail when setting null values to fields.
*/
FAIL_ON_NULL_VALUE(true),
/**
* Ignore unknown types on <code>google.protobuf.Any</code> when parsing unwrapped
* messages.
*/
IGNORE_UNKNOWN_ANY_TYPE(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, true),
/**
* Allow using the <code>json.compact</code> compact notation for
* messages. If set to true the messages will be encoded as an array
* instead of an object.
*/
WRITE_COMPACT_MESSAGES(false),
/**
* Allows using an unwrapped JSON in place of the binary content of an
* Any struct.
*/
WRITE_UNPACKED_ANY(true),
/**
* If set to true will write field names using the field ID.
*/
WRITE_FIELD_AS_NUMBER(false),
/**
* If set to true will write enum values using the enum number value.
*/
WRITE_ENUM_AS_NUMBER(SerializationFeature.WRITE_ENUMS_USING_INDEX),
/**
* Write google.proto.Timestamp values as ISO timestamp.
*/
WRITE_TIMESTAMP_AS_ISO(true),
/**
* Write google.proto.Duration as string value.
*/
WRITE_DURATION_AS_STRING(true),
;
private final DeserializationFeature deserializationFeature;
private final boolean flipMeaningOfDeserializationFeature;
private final SerializationFeature serializationFeature;
private final boolean enabledByDefault;
ProtoFeature(boolean enabledByDefault) {
this.deserializationFeature = null;
this.flipMeaningOfDeserializationFeature = false;
this.serializationFeature = null;
this.enabledByDefault = enabledByDefault;
}
ProtoFeature(DeserializationFeature deserializationFeature, boolean flip) {
this.deserializationFeature = deserializationFeature;
this.flipMeaningOfDeserializationFeature = flip;
this.serializationFeature = null;
this.enabledByDefault = flip != deserializationFeature.enabledByDefault();
}
ProtoFeature(SerializationFeature serializationFeature) {
this.deserializationFeature = null;
this.flipMeaningOfDeserializationFeature = false;
this.serializationFeature = serializationFeature;
this.enabledByDefault = serializationFeature.enabledByDefault();
}
/**
* Enable features on mapper.
*
* @param mapper Object mapper.
* @param features Features to be enabled.
* @return The mapper.
*/
public static ObjectMapper enableFeatures(ObjectMapper mapper, ProtoFeature... features) {
for (var feature : features) {
feature.enable(mapper);
}
return mapper;
}
/**
* Disable features on mapper.
*
* @param mapper Object mapper.
* @param features Features to disable.
* @return The mapper.
*/
public static ObjectMapper disableFeatures(ObjectMapper mapper, ProtoFeature... features) {
for (var feature : features) {
feature.disable(mapper);
}
return mapper;
}
/**
* Enable feature on mapper.
*
* @param mapper Object mapper.
* @return The mapper.
*/
public ObjectMapper enable(ObjectMapper mapper) {
if (serializationFeature != null) {
mapper.enable(serializationFeature);
} else if (deserializationFeature != null) {
if (flipMeaningOfDeserializationFeature) {
mapper.disable(deserializationFeature);
} else {
mapper.enable(deserializationFeature);
}
} else if (enabledByDefault) {
mapper.setConfig(mapper.getSerializationConfig().withoutAttribute(this));
mapper.setConfig(mapper.getDeserializationConfig().withoutAttribute(this));
} else {
mapper.setConfig(mapper.getSerializationConfig().withAttribute(this, true));
mapper.setConfig(mapper.getDeserializationConfig().withAttribute(this, true));
}
return mapper;
}
/**
* Disable feature on mapper.
*
* @param mapper Object mapper.
* @return The mapper.
*/
public ObjectMapper disable(ObjectMapper mapper) {
if (serializationFeature != null) {
mapper.disable(serializationFeature);
} else if (deserializationFeature != null) {
if (flipMeaningOfDeserializationFeature) {
mapper.enable(deserializationFeature);
} else {
mapper.disable(deserializationFeature);
}
} else if (enabledByDefault) {
mapper.setConfig(mapper.getSerializationConfig().withAttribute(this, false));
mapper.setConfig(mapper.getDeserializationConfig().withAttribute(this, false));
} else {
mapper.setConfig(mapper.getSerializationConfig().withoutAttribute(this));
mapper.setConfig(mapper.getDeserializationConfig().withoutAttribute(this));
}
return mapper;
}
/**
* Check if feature is enabled for serializer.
*
* @param sp The serializer provider.
* @return If feature is enabled.
*/
public boolean isEnabled(SerializerProvider sp) {
if (serializationFeature != null) {
return sp.isEnabled(serializationFeature);
}
Object o = sp.getAttribute(this);
if (o == null) {
return enabledByDefault;
}
return Boolean.TRUE.equals(o);
}
/**
* Check if feature is enabled for deserializer.
*
* @param dc The deserializer config.
* @return If feature is enabled.
*/
public boolean isEnabled(DeserializationConfig dc) {
if (deserializationFeature != null) {
if (flipMeaningOfDeserializationFeature) {
return !dc.isEnabled(deserializationFeature);
} else {
return dc.isEnabled(deserializationFeature);
}
}
Object o = dc.getAttributes().getAttribute(this);
if (o == null) {
return enabledByDefault;
}
return Boolean.TRUE.equals(o);
}
}