zio-schema icon indicating copy to clipboard operation
zio-schema copied to clipboard

Allow coercions during DynamicValue deserialization

Open jdegoes opened this issue 2 years ago • 0 comments

When attempting to deserialize a value of type A from a DynamicValue, we should be flexible in allowing reading "smaller" types from "larger" types, i.e. allow coercions.

Various examples:

  1. Allow coercing the string "123" to the number 123.
  2. Allow coercing the integer 123 to the floating-point number 123.0F.
  3. Etc.

All these coercions would be (for now) on primitive types. Therefore, one way to implement this may be to modify StandardType, to add something like:

sealed trait StandardType[A] {
  def coerce[B](that: StandardType[B]): Option[A => Either[String, B]]
}

If the types cannot be coerced under any circumstance, then coerce would return None. For example, it is not possible to coerce a Boolean into a java.time.Instant. On the other hand, if types can be coerced under some circumstances, depending on their values, then coerce can return Some, which will hold the conversion function A => Either[String, B].

The conversion function may fail, because even though some values may be coercible, other values may not be coercible. For example, strings can sometimes be coerced to numbers, but not always, because not all strings contain numbers.

By defining and placing such a coercion method on StandardType, and leaving it abstract, it will motivate implementing it on the standard type subtypes, for all types that make sense.

Then, after such coercion machinery is in place, it should be relatively straightforward to support coercions when deserializing from DynamicValue.

@thinkharderdev Any other places it can make sense to use coercion? How about during migrations?

jdegoes avatar Feb 16 '22 13:02 jdegoes