ProtoFeature.java

  1. package net.morimekta.proto.jackson;

  2. import com.fasterxml.jackson.databind.DeserializationConfig;
  3. import com.fasterxml.jackson.databind.DeserializationFeature;
  4. import com.fasterxml.jackson.databind.ObjectMapper;
  5. import com.fasterxml.jackson.databind.SerializationFeature;
  6. import com.fasterxml.jackson.databind.SerializerProvider;

  7. /**
  8.  * Providence specific features or attributes used to configure
  9.  * serialization further. These are technically 'attributes' on
  10.  * the serialization config, but is used are simple feature
  11.  * flags.
  12.  */
  13. public enum ProtoFeature {
  14.     /**
  15.      * Fail when encountering an enum value (from string) that is unknown.
  16.      */
  17.     FAIL_ON_UNKNOWN_ENUM(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, true),
  18.     /**
  19.      * Fail when encountering an unknown field on a message.
  20.      */
  21.     FAIL_ON_UNKNOWN_FIELD(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false),
  22.     /**
  23.      * Fail when setting null values to fields.
  24.      */
  25.     FAIL_ON_NULL_VALUE(true),

  26.     /**
  27.      * Ignore unknown types on <code>google.protobuf.Any</code> when parsing unwrapped
  28.      * messages.
  29.      */
  30.     IGNORE_UNKNOWN_ANY_TYPE(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, true),

  31.     /**
  32.      * Allow using the <code>json.compact</code> compact notation for
  33.      * messages. If set to true the messages will be encoded as an array
  34.      * instead of an object.
  35.      */
  36.     WRITE_COMPACT_MESSAGES(false),
  37.     /**
  38.      * Allows using an unwrapped JSON in place of the binary content of an
  39.      * Any struct.
  40.      */
  41.     WRITE_UNPACKED_ANY(true),
  42.     /**
  43.      * If set to true will write field names using the field ID.
  44.      */
  45.     WRITE_FIELD_AS_NUMBER(false),
  46.     /**
  47.      * If set to true will write enum values using the enum number value.
  48.      */
  49.     WRITE_ENUM_AS_NUMBER(SerializationFeature.WRITE_ENUMS_USING_INDEX),
  50.     /**
  51.      * Write google.proto.Timestamp values as ISO timestamp.
  52.      */
  53.     WRITE_TIMESTAMP_AS_ISO(true),
  54.     /**
  55.      * Write google.proto.Duration as string value.
  56.      */
  57.     WRITE_DURATION_AS_STRING(true),
  58.     ;
  59.     private final DeserializationFeature deserializationFeature;
  60.     private final boolean                flipMeaningOfDeserializationFeature;
  61.     private final SerializationFeature   serializationFeature;
  62.     private final boolean                enabledByDefault;

  63.     ProtoFeature(boolean enabledByDefault) {
  64.         this.deserializationFeature = null;
  65.         this.flipMeaningOfDeserializationFeature = false;
  66.         this.serializationFeature = null;
  67.         this.enabledByDefault = enabledByDefault;
  68.     }

  69.     ProtoFeature(DeserializationFeature deserializationFeature, boolean flip) {
  70.         this.deserializationFeature = deserializationFeature;
  71.         this.flipMeaningOfDeserializationFeature = flip;
  72.         this.serializationFeature = null;
  73.         this.enabledByDefault = flip != deserializationFeature.enabledByDefault();
  74.     }

  75.     ProtoFeature(SerializationFeature serializationFeature) {
  76.         this.deserializationFeature = null;
  77.         this.flipMeaningOfDeserializationFeature = false;
  78.         this.serializationFeature = serializationFeature;
  79.         this.enabledByDefault = serializationFeature.enabledByDefault();
  80.     }

  81.     /**
  82.      * Enable features on mapper.
  83.      *
  84.      * @param mapper   Object mapper.
  85.      * @param features Features to be enabled.
  86.      * @return The mapper.
  87.      */
  88.     public static ObjectMapper enableFeatures(ObjectMapper mapper, ProtoFeature... features) {
  89.         for (var feature : features) {
  90.             feature.enable(mapper);
  91.         }
  92.         return mapper;
  93.     }

  94.     /**
  95.      * Disable features on mapper.
  96.      *
  97.      * @param mapper   Object mapper.
  98.      * @param features Features to disable.
  99.      * @return The mapper.
  100.      */
  101.     public static ObjectMapper disableFeatures(ObjectMapper mapper, ProtoFeature... features) {
  102.         for (var feature : features) {
  103.             feature.disable(mapper);
  104.         }
  105.         return mapper;
  106.     }

  107.     /**
  108.      * Enable feature on mapper.
  109.      *
  110.      * @param mapper Object mapper.
  111.      * @return The mapper.
  112.      */
  113.     public ObjectMapper enable(ObjectMapper mapper) {
  114.         if (serializationFeature != null) {
  115.             mapper.enable(serializationFeature);
  116.         } else if (deserializationFeature != null) {
  117.             if (flipMeaningOfDeserializationFeature) {
  118.                 mapper.disable(deserializationFeature);
  119.             } else {
  120.                 mapper.enable(deserializationFeature);
  121.             }
  122.         } else if (enabledByDefault) {
  123.             mapper.setConfig(mapper.getSerializationConfig().withoutAttribute(this));
  124.             mapper.setConfig(mapper.getDeserializationConfig().withoutAttribute(this));
  125.         } else {
  126.             mapper.setConfig(mapper.getSerializationConfig().withAttribute(this, true));
  127.             mapper.setConfig(mapper.getDeserializationConfig().withAttribute(this, true));
  128.         }
  129.         return mapper;
  130.     }

  131.     /**
  132.      * Disable feature on mapper.
  133.      *
  134.      * @param mapper Object mapper.
  135.      * @return The mapper.
  136.      */
  137.     public ObjectMapper disable(ObjectMapper mapper) {
  138.         if (serializationFeature != null) {
  139.             mapper.disable(serializationFeature);
  140.         } else if (deserializationFeature != null) {
  141.             if (flipMeaningOfDeserializationFeature) {
  142.                 mapper.enable(deserializationFeature);
  143.             } else {
  144.                 mapper.disable(deserializationFeature);
  145.             }
  146.         } else if (enabledByDefault) {
  147.             mapper.setConfig(mapper.getSerializationConfig().withAttribute(this, false));
  148.             mapper.setConfig(mapper.getDeserializationConfig().withAttribute(this, false));
  149.         } else {
  150.             mapper.setConfig(mapper.getSerializationConfig().withoutAttribute(this));
  151.             mapper.setConfig(mapper.getDeserializationConfig().withoutAttribute(this));
  152.         }
  153.         return mapper;
  154.     }

  155.     /**
  156.      * Check if feature is enabled for serializer.
  157.      *
  158.      * @param sp The serializer provider.
  159.      * @return If feature is enabled.
  160.      */
  161.     public boolean isEnabled(SerializerProvider sp) {
  162.         if (serializationFeature != null) {
  163.             return sp.isEnabled(serializationFeature);
  164.         }
  165.         Object o = sp.getAttribute(this);
  166.         if (o == null) {
  167.             return enabledByDefault;
  168.         }
  169.         return Boolean.TRUE.equals(o);
  170.     }

  171.     /**
  172.      * Check if feature is enabled for deserializer.
  173.      *
  174.      * @param dc The deserializer config.
  175.      * @return If feature is enabled.
  176.      */
  177.     public boolean isEnabled(DeserializationConfig dc) {
  178.         if (deserializationFeature != null) {
  179.             if (flipMeaningOfDeserializationFeature) {
  180.                 return !dc.isEnabled(deserializationFeature);
  181.             } else {
  182.                 return dc.isEnabled(deserializationFeature);
  183.             }
  184.         }
  185.         Object o = dc.getAttributes().getAttribute(this);
  186.         if (o == null) {
  187.             return enabledByDefault;
  188.         }
  189.         return Boolean.TRUE.equals(o);
  190.     }
  191. }