Class: Lutaml::KeyValue::Transformation::ValueSerializer
- Inherits:
-
Object
- Object
- Lutaml::KeyValue::Transformation::ValueSerializer
- Includes:
- Model::RenderPolicy
- Defined in:
- lib/lutaml/key_value/transformation/value_serializer.rb
Overview
Serializes values (primitives and nested models) for key-value formats.
This is an independent class with explicit dependencies that can be tested in isolation from Transformation.
Instance Attribute Summary collapse
-
#format ⇒ Symbol
readonly
The serialization format (:json, :yaml, :toml).
-
#model_class ⇒ Class?
readonly
The model class for attribute lookup.
-
#register_id ⇒ Symbol?
readonly
The register ID for attribute lookup.
-
#transformation_factory ⇒ Proc
readonly
Factory lambda for creating child transformations.
Instance Method Summary collapse
-
#identity_fast_type(rule) ⇒ Object
Builtin scalars whose type registers no custom to_
serializer serialize as the value itself — Type::Value#to_ 's default — without the wrap-allocate-cast ceremony per field. -
#initialize(format:, register_id:, transformation_factory:, model_class: nil) ⇒ ValueSerializer
constructor
Initialize the ValueSerializer with explicit dependencies.
-
#nested_model?(rule) ⇒ Boolean
Check if a value is a nested model based on the rule.
-
#serialize_item(value, rule, options = {}) ⇒ Object?
Serialize a value for an item (handles nested models and primitives).
-
#serialize_nested_model(value, rule, options = {}) ⇒ Hash?
Serialize a nested model to a hash representation.
- #serialize_plan(rule) ⇒ Object
-
#serialize_primitive(value, rule) ⇒ Object
Serialize a primitive value to the appropriate representation.
-
#serialize_union(value, options) ⇒ Object
Union: dispatch on the value's own class (stateless).
-
#serialize_value_plan(rule) ⇒ Object
Per-rule serialize plan: the type class for builtin scalars with no custom to_
serializer (identity serialization), nil otherwise.
Methods included from Model::RenderPolicy
derived_attribute_for?, #should_skip_delegated_value?, #should_skip_value?
Constructor Details
#initialize(format:, register_id:, transformation_factory:, model_class: nil) ⇒ ValueSerializer
Initialize the ValueSerializer with explicit dependencies.
40 41 42 43 44 45 46 |
# File 'lib/lutaml/key_value/transformation/value_serializer.rb', line 40 def initialize(format:, register_id:, transformation_factory:, model_class: nil) @format = format @register_id = register_id @transformation_factory = transformation_factory @model_class = model_class end |
Instance Attribute Details
#format ⇒ Symbol (readonly)
Returns The serialization format (:json, :yaml, :toml).
23 24 25 |
# File 'lib/lutaml/key_value/transformation/value_serializer.rb', line 23 def format @format end |
#model_class ⇒ Class? (readonly)
Returns The model class for attribute lookup.
32 33 34 |
# File 'lib/lutaml/key_value/transformation/value_serializer.rb', line 32 def model_class @model_class end |
#register_id ⇒ Symbol? (readonly)
Returns The register ID for attribute lookup.
26 27 28 |
# File 'lib/lutaml/key_value/transformation/value_serializer.rb', line 26 def register_id @register_id end |
#transformation_factory ⇒ Proc (readonly)
Returns Factory lambda for creating child transformations.
29 30 31 |
# File 'lib/lutaml/key_value/transformation/value_serializer.rb', line 29 def transformation_factory @transformation_factory end |
Instance Method Details
#identity_fast_type(rule) ⇒ Object
Builtin scalars whose type registers no custom to_
196 197 198 199 200 201 202 203 204 205 |
# File 'lib/lutaml/key_value/transformation/value_serializer.rb', line 196 def identity_fast_type(rule) type = rule.attribute_type return nil unless type.is_a?(::Class) && type < ::Lutaml::Model::Type::Value serializer = ::Lutaml::Model::Type::Value .format_type_serializer_for(@format, type) has_custom_to = serializer && serializer[:to] has_custom_from = ::Lutaml::Model::Attribute.custom_from_probe?(type) type unless has_custom_to || has_custom_from end |
#nested_model?(rule) ⇒ Boolean
Check if a value is a nested model based on the rule.
99 100 101 102 103 |
# File 'lib/lutaml/key_value/transformation/value_serializer.rb', line 99 def nested_model?(rule) # Use include? instead of < because < returns nil (not false) for non-subclasses rule.attribute_type.is_a?(Class) && rule.attribute_type.include?(Lutaml::Model::Serialize) end |
#serialize_item(value, rule, options = {}) ⇒ Object?
Serialize a value for an item (handles nested models and primitives).
This is the main entry point for value serialization.
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/lutaml/key_value/transformation/value_serializer.rb', line 56 def serialize_item(value, rule, = {}) return nil if value.nil? return nil if Lutaml::Model::Utils.uninitialized?(value) # Compiled serialize plan (TODO.perf/07): the rule-invariant # probes — identity-fast builtin scalars, Reference, union, # nested-model classification — resolve once per rule; the # per-field hash lookups dominated primitive-heavy docs. plan = serialize_plan(rule) if (fast = plan[:identity_type]) && value.instance_of?(fast) return value end # Check for Reference type first - even if value is a Serializable, # it should be serialized as a key, not as a nested model if plan[:reference] return serialize_reference(value, rule) end if plan[:union] serialize_union(value, ) elsif plan[:nested] serialize_nested_model(value, rule, ) else serialize_primitive(value, rule) end end |
#serialize_nested_model(value, rule, options = {}) ⇒ Hash?
Serialize a nested model to a hash representation.
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/lutaml/key_value/transformation/value_serializer.rb', line 111 def serialize_nested_model(value, rule, = {}) validate_nested_model_type!(value, rule) # Determine the actual type for polymorphism support actual_type = determine_actual_type(value, rule) uses_polymorphism = actual_type != rule.attribute_type # Get or create child transformation child_transformation = if uses_polymorphism create_transformation(actual_type) else rule.child_transformation || create_transformation(rule.attribute_type) end if child_transformation transform_nested_model(value, child_transformation, ) else serialize_primitive(value, rule) end end |
#serialize_plan(rule) ⇒ Object
183 184 185 186 187 188 189 190 191 |
# File 'lib/lutaml/key_value/transformation/value_serializer.rb', line 183 def serialize_plan(rule) @serialize_plans ||= {} @serialize_plans[rule] ||= { identity_type: identity_fast_type(rule), reference: reference_type?(rule), union: ::Lutaml::Model::Type::Union.rule?(rule), nested: nested_model?(rule), } end |
#serialize_primitive(value, rule) ⇒ Object
Serialize a primitive value to the appropriate representation.
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/lutaml/key_value/transformation/value_serializer.rb', line 138 def serialize_primitive(value, rule) return nil if value.nil? return nil if Lutaml::Model::Utils.uninitialized?(value) # For Reference types, use attribute's serialize method if reference_type?(rule) return serialize_reference(value, rule) end # For Serializable types, use to_#{format} method if rule.attribute_type.is_a?(Class) && rule.attribute_type < Lutaml::Model::Serialize validate_serializable_type!(value, rule) return value.public_send(:"to_#{format}") end # Wrap value in type and call to_#{format} if rule.attribute_type.is_a?(Class) && rule.attribute_type < Lutaml::Model::Type::Value wrapped_value = rule.attribute_type.new(value) wrapped_value.public_send(:"to_#{format}") else value end end |
#serialize_union(value, options) ⇒ Object
Union: dispatch on the value's own class (stateless). A model member serializes via its class transformation; a scalar emits as-is.
86 87 88 89 90 91 92 93 |
# File 'lib/lutaml/key_value/transformation/value_serializer.rb', line 86 def serialize_union(value, ) unless value.is_a?(Lutaml::Model::Serialize) return Lutaml::Model::Type::Union.serialize_scalar(value, format) end transform_nested_model(value, create_transformation(value.class), ) end |
#serialize_value_plan(rule) ⇒ Object
Per-rule serialize plan: the type class for builtin scalars with
no custom to_
169 170 171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/lutaml/key_value/transformation/value_serializer.rb', line 169 def serialize_value_plan(rule) @serialize_value_plans ||= {} @serialize_value_plans[rule] ||= begin attr = model_class.attributes(register_id)&.[](rule.attribute_name) attr ||= model_class.attributes&.[](rule.attribute_name) { attr: attr, reference: attr && attr.unresolved_type == Lutaml::Model::Type::Reference, nested: rule.attribute_type.is_a?(Class) && rule.attribute_type < Lutaml::Model::Serialize, } end end |