zio-schema
zio-schema copied to clipboard
Allow coercions during DynamicValue deserialization
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:
- Allow coercing the string
"123"
to the number123
. - Allow coercing the integer
123
to the floating-point number123.0F
. - 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?