Skip to content

module Athena::Serializer::ExclusionStrategies::ExclusionStrategyInterface #

Represents a specific exclusion strategy.

Custom logic can be implemented by defining a type with this interface. It can then be used via ASR::Context#add_exclusion_strategy.

Example#

struct OddNumberExclusionStrategy
  include Athena::Serializer::ExclusionStrategies::ExclusionStrategyInterface

  # :inherit:
  #
  # Skips serializing odd numbered values
  def skip_property?(metadata : ASR::PropertyMetadataBase, context : ASR::Context) : Bool
    # Don't skip if the value is nil
    return false unless value = (metadata.value)

    # Only skip on serialization, if the value is an number, and if it's odd.
    context.is_a?(ASR::SerializationContext) && value.is_a?(Number) && value.odd?
  end
end

serialization_context = ASR::SerializationContext.new
serialization_context.add_exclusion_strategy OddNumberExclusionStrategy.new

deserialization_context = ASR::DeserializationContext.new
deserialization_context.add_exclusion_strategy OddNumberExclusionStrategy.new

record Values, one : Int32 = 1, two : Int32 = 2, three : Int32 = 3 do
  include ASR::Serializable
end

ASR.serializer.serialize Values.new, :json, serialization_context                                 # => {"two":2}
ASR.serializer.deserialize Values, %({"one":4,"two":5,"three":6}), :json, deserialization_context # => Values(@one=4, @three=6, @two=5)

Annotation Configurations#

Custom annotations can be defined using ADI.configuration_annotation. These annotations will be exposed at runtime as part of the properties' metadata within exclusion strategies via ASR::PropertyMetadata#annotation_configurations. The main purpose of this is to allow for more advanced annotation based exclusion strategies.

# Define an annotation called `IsActiveProperty` that accepts an optional `active` field.
ADI.configuration_annotation IsActiveProperty, active : Bool = true

# Define an exclusion strategy that should skip "inactive" properties.
struct ActivePropertyExclusionStrategy
  include Athena::Serializer::ExclusionStrategies::ExclusionStrategyInterface

  # :inherit:
  def skip_property?(metadata : ASR::PropertyMetadataBase, context : ASR::Context) : Bool
    # Don't skip on deserialization.
    return false if context.direction.deserialization?

    ann_configs = metadata.annotation_configurations

    # Skip if the property has the annotation and it's "inactive".
    ann_configs.has?(IsActiveProperty) && !ann_configs[IsActiveProperty].active
  end
end

record Example, id : Int32, first_name : String, last_name : String, zip_code : Int32 do
  include ASR::Serializable

  @[IsActiveProperty]
  @first_name : String

  @[IsActiveProperty(active: false)]
  @last_name : String

  # Can also be defined as a positional argument.
  @[IsActiveProperty(false)]
  @zip_code : Int32
end

serialization_context = ASR::SerializationContext.new
serialization_context.add_exclusion_strategy ActivePropertyExclusionStrategy.new

ASR.serializer.serialize Example.new(1, "Jon", "Snow", 90210), :json, serialization_context # => {"id":1,"first_name":"Jon"}

Direct including types

Athena::Serializer::ExclusionStrategies::Disjunct Athena::Serializer::ExclusionStrategies::Groups Athena::Serializer::ExclusionStrategies::Version

Methods#

abstract #skip_property?(metadata : ASR::PropertyMetadataBase, context : ASR::Context) : Bool#

Returns true if a property should NOT be (de)serialized.

View source