Proposal: optional_subfield
for use
style nested optional decoding
#4202
jhillyerd
started this conversation in
Ideas & suggestions
Replies: 1 comment 3 replies
-
Hello! This would be written today like so: use value <- decode.then(decode.optionally_at(
["a", "b", "c"],
None,
decode.optional(decode.string),
)) We could possibly add this new function, but it's best to wait some time to get an understanding of how the current API is going. The stdlib is very conservative so we delaying any additions is good. |
Beta Was this translation helpful? Give feedback.
3 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Problem Summary
The new
use
decoder API lacks an easy way to cherry-pick a nested value when the path to that value may have missing or null elements. It is possible with the current API by mixingoptional_field
,optional
, andat
– but the method is not simple or easily discoverable.Cherry-picking optional nested values is very helpful when the Gleam type you wish to decode into does not closely match the schema you are decoding from, or if you don’t have a schema and are iterating on the design of your type & decoder.
Proposed Solution Summary
Add an
optional_subfield
function to thedynamic/decode
module, similar to the existingsubfield
function, but allowing for a default value, signature:In addition, we can consider modifying the existing
optionally_at
function to handle “null” and not just missing values. Its current behavior might be considered a bug, but altering it might also be considered an API change.Problem Detail
Writing a decoder to optionally extract a value for “c” from the below JSON samples is more difficult than one would expect.
{"id": 1}
{"id": 1, "a": null}
{"id": 1, "a": {"b": null}}
{"id": 1, "a": {"b": {"c": null}}}
{"id": 1, "a": {"b": {"c": “target value”}}}
There are several difficulties:
use
decoder API, so one must start withoptional_field
and then pass in regular Decoder to navigate deeper into the treeoptionally_at
does not handle null values along the path, only missing ones (see failure example below)one_of
+at
can be a concise way to decode a nested value, it does not allow the caller to differentiate a missing value from an invalid one, masking errors (see failure example below)optional
andat
results in a nested set of Options that need to be flattenedEach of the current field type decoders has a matching optional variant, except one. This was confusing to me:
at
hasoptionally_at
field
hasoptional_field
subfield
has no optional variantProblem Example Code
This example illustrates the existing way to decode this, along with some assertions you may use to test alternatives if you feel I’ve missed something. It should be usable in a fresh gleam project after running
gleam add gleam_json
.The example below succeeds, but the combination of
optional_field
,optional
, andat
is difficult to read, non-obvious, and requires a matching chain ofoption.flatten
calls to unwrap the result.Failing Examples
Trying to use optionally_at instead:
Will fail to decode when
a
isnull
:Trying to use
one_of
instead:Will decode a None, instead of failing when given a number instead of a string:
Solution Detail
My ideal solution would allow the decoder block above to be written as:
The
optional_subfield
function can be implemented by copying the existingoptional_field
function, and modifying it to useindex
instead ofbare_index
. The resulting function body is only 8 lines of code, which should not present a heavy maintenance burden.A potential implementation, with tests can be seen here: jhillyerd/stdlib@0f09583
Beta Was this translation helpful? Give feedback.
All reactions