json_serializable.dart
json_serializable.dart copied to clipboard
Map with enum keys is serialized as List, but deserialized as Map
Just had some fun figuring out why this fails:
import 'package:equatable/equatable.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:json_annotation/json_annotation.dart';
part 'enum.g.dart';
enum A { a, b }
@JsonSerializable(anyMap: true, explicitToJson: true)
class B extends Equatable {
final Map<A, int?> map;
Iterable<int?> get values => map.values;
const B([Map<A, int?>? values]) : map = values ?? const {A.a: 1, A.b: 2};
B update(A a, int value) {
return B(Map.from(map)..[a] = value);
}
factory B.fromJson(Map<String, dynamic> json) {
return _$BFromJson(json);
}
Map<String, dynamic> toJson() => _$BToJson(this);
@override
List<Object?> get props => map.values.toList();
}
void main() {
test('description', () {
final instance = const B().update(A.a, 3);
expect(B.fromJson(instance.toJson()), equals(instance));
});
}
Having a getter with the same name as a constructor parameter leads to that one's values being serialized rather than the actual field. It would be great to
- ideally have this not compile without explicitly making it,
- generate a warning during build runner,
- maybe reflect this somewhere on the pub page? I might have missed it but at least the word "getter" is not present.
Since the getter/field is the thing annotated, I go with that type. Ideally the to/from types should be consistent!
I agree on the "ideally" part and have adjusted my code correspondingly - just meant to give some input on a bug that is potentially hard to pinpoint and could maybe be made easier to avoid.
Even if you don't think making adjustments is justified, at least now there is something for any fellow googlers to find :)