Closed Lars-Sommer closed 1 year ago
Interesting 🤓 thanks for detailed pre-investigation. I'll take a look deeper soon, since I have no idea yet off the top of my head.
Here we go preferred workaround would be to - rename enum values all camelCase
since it will be aligned with the linter rule below
as well aligned with the Dart sdk core codebase which is using this lint rule.
@JsonSerializable()
enum EDeviceRadioType { loRa, nBIoT, mBus, mobileInternet, wMBus }
According to this doc assumption is that your Dart code IS following camelCase
style initially. Main misunderstanding comes from braking this assumption by giving the initial code in PascalCase
So you should be good to go just by renaming the enum values, and those values will be transformed accordingly to case style option.
And what if you need to have those enum values to still be transmitted using completely custom logic? you can do that by providing enum values mappings, like this
JsonMapper().useAdapter(
JsonMapperAdapter(enumValues: {
EDeviceRadioType: EnumDescriptor(
values: EDeviceRadioType.values,
mapping: <EDeviceRadioType, String>{
EDeviceRadioType.loRa: 'LORa',
EDeviceRadioType.nBIoT: 'NB-IoT',
EDeviceRadioType.mBus: '_MBUs_',
EDeviceRadioType.wMBus: 'WMBUS',
// ...
})
})
);
Hope this helps 😄
Thanks alot, I will look into it in the near future and return :)
I´ve tried your adapter solution and renamed the enums with camelCase. This works fine. I have to do this because it is our backend who has defined and named these enums.
So I guess I´ve got to rename all my enum definitions in the app, and then create the corresponding adapter mappings. It would be nice if this was not nescacary, but I´m glad there is some kind of solution :)
I mean this should work even w/o adapter, just by lower casing first letter of each enum entry. These adapter mappings are for non standard cases primarily, when there is no suited predefined casing.
I cannot get it to work unless I create the adapter. This is my new enum definition:
enum EDeviceRadioType { loRa, nbIot, mBus, mobileInternet, wmBus }
This parsing works:
const json = '{ "Id": "6267a8bf0a66709b2c7021bd", "Radio": "WMBus" }';
TestModel model = JsonMapper.deserialize<TestModel>(json);
But similiar to the problem I mentioned in the original question, the deserializer cannot parse the enum when the object is nested, in this case in an array:
const json = '[{ "Id": "6267a8bf0a66709b2c7021bd", "Radio": "WMBus" }]';
List<TestModel> models = JsonMapper.deserialize<List<TestModel>>(json);
Error: "type 'Null' is not a subtype of type 'EDeviceRadioType' of 'value'"
If I create the adapter, it works.
I´ve also just tried to revert the enum renaming to the original values (WMBus etc.), and the situation is the same; I can parse a single object, but not when it is in an array or has a parent.
🤓
Also, you have a caseInsensitive
flag in the EnumDescriptor
class to declare enum as such. This way you can omit listing all the values in mappings.
I'm still trying to solve this issue in a more elegant way, so it's officially a bug.
I´ve tried upgrading to dart_json_mapper: ^2.2.7
and made a quick test, and it seems I can now parse my WMBus enum in both a model and a model in an array. Without the extra adapter setting. So I guess it works!
Thanks alot - you´re awesome :)
I have the following classes:
And this enum:
This deserialization works:
But this does not work:
The deserialize function fails with:
_TypeError (type 'Null' is not a subtype of type 'EDeviceRadioType' of 'value')
But if I change the enum to a type which does not have a following upper case character, the deserialization works:
As far as I can read, WMBus and alike should be valid PascalCase. But nonetheless, it is weird that it works if the model is not wrapped in a parent. Am I missing anything here? 🤔