Class: Cuprum::Rails::Serializers::Json::PropertiesSerializer

Inherits:
BaseSerializer
  • Object
show all
Defined in:
lib/cuprum/rails/serializers/json/properties_serializer.rb

Overview

Generates a JSON representation of the object’s properties.

Defined properties are inherited from the parent serializer. This allows you to extend existing serializers with additional functionality.

Examples:

Serializing an existing property.

User = Struct.new(:first_name, :last_name, :salary, :department)
class FirstNameSerializer < Cuprum::Rails::Serializers::Json::PropertySerializer
  property :first_name, scope: :first_name
end

user       = User.new('Alan', 'Bradley')
serializer = FirstNameSerializer.new
serializer.call(user, context: context)
#=> {
  'first_name' => 'Alan'
}

Serializing a compound property.

User = Struct.new(:first_name, :last_name, :salary, :department)
class FullNameSerializer < Cuprum::Rails::Serializers::Json::PropertySerializer
  property :full_name do |user|
    "#{user.first_name} #{user.last_name}"
  end
end

user       = User.new('Alan', 'Bradley')
serializer = FullNameSerializer.new
serializer.call(user, context: context)
#=> {
  'full_name' => 'Alan Bradley'
}

Using a custom serializer.

User = Struct.new(:first_name, :last_name, :salary, :department)
class SalarySerializer < Cuprum::Rails::Serializers::Json::PropertySerializer
  property :salary,
    scope:      :salary,
    serializer: BigDecimalSerializer
end

user       = User.new('Alan', 'Bradley', BigDecimal('100000'))
serializer = SalarySerializer.new
serializer.call(user, context: context)
#=> {
  'salary' => '0.1e6'
}

Using a nested scope.

Department = Struct.new(:name)
User       = Struct.new(:first_name, :last_name, :salary, :department)
class DepartmentSerializer < Cuprum::Rails::Serializers::Json::PropertySerializer
  property :department, scope: %i[department name]
end

user       = User.new('Alan', 'Bradley', nil, Department.new('Engineering'))
serializer = DepartmentSerializer.new
serializer.call(user, context: context)
#=> {
  'department' => 'Engineering'
}

Using a custom mapping.

User = Struct.new(:first_name, :last_name, :hire_date)
class HireDateSerializer < Cuprum::Rails::Serializers::Json::PropertySerializer
  property(:hire_date, scope: :hire_date) { |value| value&.iso8601 }
end

user       = User.new('Alan', 'Bradley', Date.new(1977, 5, 25))
serializer = HireDateSerializer.new
serializer.call(user, context: context)
#=> {
  'hire_date' => '1977-05-25'
}

Direct Known Subclasses

AttributesSerializer

Defined Under Namespace

Classes: AbstractSerializerError, SerializedProperty

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from BaseSerializer

instance

Class Method Details

.propertiesObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Enumerates the properties defined for the class and its ancestors.



151
152
153
154
155
156
157
158
# File 'lib/cuprum/rails/serializers/json/properties_serializer.rb', line 151

def properties
  ancestors
    .select do |ancestor|
      ancestor < Cuprum::Rails::Serializers::Json::PropertiesSerializer
    end # rubocop:disable Style/MultilineBlockChain
    .reverse_each
    .reduce({}) { |hsh, ancestor| hsh.merge(ancestor.own_properties) }
end

.property(name, scope: nil, serializer: nil) {|value| ... } ⇒ Object

Registers the property to be serialized.

Parameters:

  • name (String, Symbol)

    the name of the property to serialize. This will determine the hash key of the serialized value.

  • serializer (#call) (defaults to: nil)

    the serializer used to serialize the value. If no serializer is given, the default serializer (if any) will be used.

  • scope (String, Symbol, Array<String, Symbol>) (defaults to: nil)

    the path to the value to serialize, if any.

Yields:

  • If a block is given, the block is used to transform the scoped value prior to serialization.

Yield Parameters:

  • value (Object)

    the scoped value.

Yield Returns:

  • (Object)

    the transformed value.

Raises:

  • AbstractSerializerError when attempting to define a serialized attribute on an abstract class.

  • ArgumentError unless a scope, serializer, or block is given.

See Also:

  • Cuprum::Rails::Serializers::Json::PropertiesSerializer::ClassMethods#property


125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/cuprum/rails/serializers/json/properties_serializer.rb', line 125

def property(name, scope: nil, serializer: nil, &block) # rubocop:disable Metrics/MethodLength
  require_concrete_class!
  validate_property_name!(name)
  validate_scope!(scope)
  validate_serializer!(serializer)

  unless scope || serializer || block_given?
    raise ArgumentError,
      'must provide a scope, a serializer, or a mapping block'
  end

  prop_key   = name.intern
  serialized = SerializedProperty.new(
    mapping:    block || :itself.to_proc,
    name:       name.to_s,
    scope:      scope,
    serializer: serializer
  )
  own_properties[prop_key] = serialized

  prop_key
end

Instance Method Details

#call(object, context:) ⇒ Hash<String, Object] a JSON-compatible representation of the object's properties.

Serializes the object’s properties as JSON.

Parameters:

  • object (Object)

    The object to convert to JSON.

  • context (Cuprum::Rails::Serializers::Context)

    The serialization context, which includes the configured serializers for attributes or collection items.

Returns:

  • (Hash<String, Object] a JSON-compatible representation of the object's properties.)

    Hash<String, Object] a JSON-compatible representation of the object’s properties.



235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
# File 'lib/cuprum/rails/serializers/json/properties_serializer.rb', line 235

def call(object, context:) # rubocop:disable Metrics/MethodLength
  return super(nil, context: context) if object.nil?

  self.class.properties.each_value.with_object({}) do |property, hsh|
    value      = property.value_for(object)
    mapped     = property.mapping.call(value) if property.mapping
    serialized =
      if property.serializer
        property.serializer.call(mapped, context: context)
      else
        super(mapped, context: context)
      end

    hsh[property.name] = serialized
  end
end