decode function for keyed varients
I think with the current API the expected way to solve varients is using one_of this doesn't give very good errors.
I have been using the following function in several projects. It decodes first a discriminator then picks a subsequent decoder based on it.
This allows it to show a specific error for the discriminator, and then good errors if the discriminator is known but it still fails to decode.
Here is the function https://github.com/CrowdHailer/oas/blob/main/src/oas/decodex.gleam#L3
Check the tests for using it and the errors it gives https://github.com/CrowdHailer/oas/blob/main/test/oas/decodex_test.gleam
I'm sure there's an argument for not extending the standard library, in which case I'd be interested in the best way to define a decoder (just a decoder without an essentially similar discriminate function extracted) that gives useful errors.
The proposal in this issue is to add a discriminate function the same or similar to the one I have linked here
What advantage would this have over the approach the documentation details for decoding these?
The example in the doc's is too simplistic, because everything after the switch is a success.
I'll try an use the approach as I understand it from the docs.
pub type Thing {
Foo(String)
Bar(Int)
}
pub fn demo_test() {
let decoder = {
use decoded_string <- decode.field("type", decode.string)
case decoded_string {
// Return succeeding decoders for valid strings
"foo" -> {
use foo <- decode.field("foo", decode.string)
decode.success(Foo(foo))
}
"bar" -> {
use bar <- decode.field("bar", decode.int)
decode.success(Bar(bar))
}
// Return a failing decoder for any other strings
_ -> decode.failure(Bar(0), "Thing")
}
}
decode.run(
dynamic.properties([#(dynamic.string("type"), dynamic.int(1))]),
decoder,
)
|> echo
// Error([DecodeError(expected: "String", found: "Int", path: ["type"]), DecodeError(expected: "Thing", found: "Dict", path: [])])
}
Running this returns two errors. the first is valid. The second in my mind is erroneous.
The error for this decode is also not great
decode.run(
dynamic.properties([#(dynamic.string("type"), dynamic.string(""))]),
decoder,
)
|> echo
// Error([DecodeError(expected: "Thing", found: "Dict", path: [])])
Thing is a Dict so this error is also a bit misleading.
When trying to look at 1k plus lines of open api spec I've lost time to both of these errors.