-
Notifications
You must be signed in to change notification settings - Fork 413
Add aliases
to JsonValue
to enum value to be decoded from different JSON values
#1459
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
Ideally we'd have a couple of tests to validate the failure cases, but I get that those can be tricky to add. |
@kevmoo What would be the failure cases for this PR? Can you give an example? |
Unsupported types in the set is the big one. |
Ah, yes, the idea is to mimic I am going to work on this test. |
You'll need to rebase this fix. |
Mmm, I had made a regular merge, but GitHub is saying to me that "this branch must not contain merge commits", so I rewrote the commits using a rebase instead, but it is still giving me this message. |
Well, the test that did not pass locally passed here, so we are good with it. |
@kevmoo Is there something preventing the code review from proceeding? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like the repeated map EVERYWHERE for one-off feature.
Could you noodle on that a bit?
@@ -31,21 +34,45 @@ bool? enumFieldWithNullInEncodeMap(DartType targetType) { | |||
return enumMap.values.contains(null); | |||
} | |||
|
|||
String? enumValueMapFromType( | |||
String? enumMapsFromType( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Undo this rename. Makes reviewing more tricky.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
const _$GreekEnumMap = { | ||
Greek.alpha: 'alpha', | ||
Greek.beta: 'beta', | ||
Greek.gamma: 'gamma', | ||
Greek.delta: 'delta', | ||
}; | ||
|
||
// ignore: unused_element | ||
const _$GreekEnumDecodeMap = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So we're changing the generated code and creating a NEW map, even if the dev doesn't use the new feature?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kevmoo Yes, basically.
The old map is left as is. However, in the current code, the map is used both for encoding and decoding. Decoding is done by linearly checking if an entry has the expected value for that key. It works similar to a Bimap.
By using two maps, we have O(1) access to the expected decoded value. But this is only a consequence of this approach, and I don't even think it will make any difference in practice unless someone decodes an outstanding quantity of Json values.
The main point is that if we introduce aliases, we have an asymmetric relationship between the two sets (the sets of encoded and decoded values). We want encoding to have a single resulting value (it is the one defined by the first parameter of the JsonValue
constructor), but it can be decoded by more than one value (which is this same value + the ones declared in the alias
parameter).
Because of this, we can't work with a single map anymore unless:
- We revert the map and key values, so we avoid duplicated keys.
- We guarantee that the first value is always the one that is expected when encoding.
Another approach could be to use two maps, the one we already have and an optional map aliases
that will only be generated if aliases are used. Then, in the $enumDecodeWithDecodeMap
function, we accept an optional aliases
map as parameter, which, if passed, will first check for the entries like it is doing today and, if not found, it will try to find it in the passed aliases
map (if any), falling back to a runtime error as it is today.
This could work, but I don't think it is a better approach than what I chose to use on this PR. I just splits the map into two, which guarantees O(1) access and a clear distinction between encoding/decoding expectations.
Maybe you have a third idea about how to tackle this issue?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Ps. the $enumDecode
function is not even used anymore, I just didn't remove it entirely because I don't know if it would constitute a breaking change. Supposedly not, because we don't expose it in the public API, but I wanted to check with you before. If we are good, $enumDecodeWithDecodeMap
can be renamed to $enumDecode
, as it replaces its purpose completely with this approach)
Solves #1380.
Adds a parameter to
JsonValue
calledaliases
, which accepts a list of values that can be alternatively used to decode a JSON.Example:
With the code above, all of
200
,201
and202
would be decoded asStatusCode.success
.When calling
toJson
, however, thevalue
parameter is used. In this case,200
.Notes
$enumDecode
and$enumDecodeNullable
were not changed because they are public and there are packages that depend on them. Instead,$enumDecodeWithDecodeMap
and$enumDecodeNullableWithDecodeMap
were introduced. We may want to deprecate the former at some point and remove them in a major version.