diff --git a/lib/typed/serializer.rb b/lib/typed/serializer.rb index 5dec483..c370edb 100644 --- a/lib/typed/serializer.rb +++ b/lib/typed/serializer.rb @@ -34,11 +34,19 @@ def serialize(struct) def deserialize_from_creation_params(creation_params) results = schema.fields.map do |field| value = creation_params.fetch(field.name, nil) + coercer = Coercion::CoercerRegistry.instance.select_coercer_by(type: field.type) if value.nil? && !field.default.nil? Success.new(Validations::ValidatedValue.new(name: field.name, value: field.default)) elsif value.nil? || field.works_with?(value) field.validate(value) + elsif !coercer.nil? + result = coercer.new.coerce(type: field.type, value:) + if result.success? + field.validate(result.payload) + else + Failure.new(Validations::ValidationError.new(result.error.message)) + end elsif field.type.class <= T::Types::Union errors = [] validated_value = T.let(nil, T.nilable(Typed::Result[Typed::Validations::ValidatedValue, Typed::Validations::ValidationError])) @@ -60,13 +68,7 @@ def deserialize_from_creation_params(creation_params) validated_value.nil? ? Failure.new(Validations::ValidationError.new(errors.map(&:message).join(", "))) : validated_value else - coercion_result = Coercion.coerce(type: field.type, value:) - - if coercion_result.success? - field.validate(coercion_result.payload) - else - Failure.new(Validations::ValidationError.new(coercion_result.error.message)) - end + Failure.new(Validations::ValidationError.new("Coercer not found for type #{field.type}.")) end end diff --git a/test/typed/hash_serializer_test.rb b/test/typed/hash_serializer_test.rb index 49c3f1b..ab1dc8b 100644 --- a/test/typed/hash_serializer_test.rb +++ b/test/typed/hash_serializer_test.rb @@ -109,6 +109,20 @@ def test_with_boolean_it_can_deserialize assert_payload(NEW_YORK_CITY, result) end + def test_with_boolean_string_false_it_can_deserialize + result = Typed::HashSerializer.new(schema: Typed::Schema.from_struct(City)).deserialize({name: "New York", capital: "false"}) + + assert_success(result) + assert_payload(NEW_YORK_CITY, result) + end + + def test_with_boolean_string_true_it_can_deserialize + result = Typed::HashSerializer.new(schema: Typed::Schema.from_struct(City)).deserialize({name: "DC", capital: "true"}) + + assert_success(result) + assert_payload(DC_CITY, result) + end + def test_with_array_it_can_deserialize result = Typed::HashSerializer.new(schema: Typed::Schema.from_struct(Country)).deserialize({name: "US", cities: [NEW_YORK_CITY, DC_CITY], national_items: {bird: "bald eagle", anthem: "The Star-Spangled Banner"}}) diff --git a/test/typed/json_serializer_test.rb b/test/typed/json_serializer_test.rb index ac04529..538bf24 100644 --- a/test/typed/json_serializer_test.rb +++ b/test/typed/json_serializer_test.rb @@ -60,6 +60,20 @@ def test_with_boolean_it_can_deserialize assert_payload(NEW_YORK_CITY, result) end + def test_with_boolean_string_false_it_can_deserialize + result = Typed::JSONSerializer.new(schema: Typed::Schema.from_struct(City)).deserialize('{"name":"New York","capital":"false"}') + + assert_success(result) + assert_payload(NEW_YORK_CITY, result) + end + + def test_with_boolean_string_true_it_can_deserialize + result = Typed::JSONSerializer.new(schema: Typed::Schema.from_struct(City)).deserialize('{"name":"DC","capital":"true"}') + + assert_success(result) + assert_payload(DC_CITY, result) + end + def test_with_array_it_can_deep_deserialize result = Typed::JSONSerializer.new(schema: Typed::Schema.from_struct(Country)).deserialize('{"name":"US","cities":[{"name":"New York","capital":false},{"name":"DC","capital":true}],"national_items":{"bird":"bald eagle","anthem":"The Star-Spangled Banner"}}')