Open SpeedReach opened 11 months ago
I think I just have a bug in the @JsonValue
case.
If you remove the @JsonValue(1)
annotation, how does the map change?
I think I just have a bug in the
@JsonValue
case. If you remove the@JsonValue(1)
annotation, how does the map change?
The generated enum map will use their values name as keys
const _$SlotEnumMap = {
Slot.slot1: 'slot1',
Slot.slot2: 'slot2',
Slot.slot3: 'slot3',
};
@kevmoo yes, it works fine in other cases. It only happens when enums are used as json keys and is annotated with int values. It's an edgy case that might need specific handling. The solution I proposed will only transfer to the code when atleast one enum is annotated with int.
I think the code is correct, honestly!
The input value can be either a String '3'
or an int 1
or 2
and it's converted correctly.
It converts to a int, shouldn't json's keys always be strings?
It causes wierd errors like this.
final object = MyClass(inv: {Slot.slot1: "ww", Slot.slot3: "ww"});
final json = object.toJson();
final deserialized = MyClass.fromJson(json);
throws type '_Map<Object, String>' is not a subtype of type 'Map<String, dynamic>' in type cast
in the fromJson method.
Even the jsonEncode in standard lib doesn't work.
final object = MyClass(inv: {Slot.slot1: "ww", Slot.slot3: "ww"});
final json = object.toJson();
final deserialized = jsonEncode(json);
throws Converting object to an encodable object failed: _Map len:2
Hrm...let me look again...
Yeah. This is crazy complex.
Effectively, (now) you CANNOT use an enum as a Map key AND set a @JsonValue
to anything other than a String
.
We'd need to create some funky custom version of _$SlotEnumMap
that's SPECIFIC to an enum used as a Map
key where the values are pre-converted to the corresponding String values.
We CAN'T just to toString
because some values are encoded with something other than their toString
– like DateTime
.
We could/should throw an error here and say "hey, you can't use an enum here" to be more clear this is not supported.
I read the doc and swa that only int and String are the supported enum values. This should make it less complex?
I read the doc and swa that only int and String are the supported enum values. This should make it less complex?
Not really. I could just throw in a toString
but that's...cheating. And would make things more complex later.
https://github.com/google/json_serializable.dart/blob/e2c8badaee4e36893e13c4073375a8ea035f2403/json_serializable/README.md?plain=1#L112-L113 The doc referenced above
I could open a pr for throwing the error, when should we throw it?
@SpeedReach not outdated, but it's not specific enough to handle the case where @JsonValue
is used.
You could try for a PR, but it's CRAZY complex to do it cleanly. I wrote most of this package. To do the plumbing correctly will be quite tough. I appreciate the enthusiasm, but it'd be a LOT of work.
Problem
generated enum map
Generated toJson:
Since enums can be Map keys, and enums can be tranfered to int with JsonValue. This produces a out come that the json key is a int.
Generated fromJson:
I don't think this should happen, since json's key should always be a String.
A solution would be:
Generated toJson:
Generated fromJson:
enumDecodeJsonKey would be a helper specific for enum map keys, would have something like.
If this looks nice , I'd be happy to work on this and submit a pr!