json_serializable.dart
json_serializable.dart copied to clipboard
Serializer ignores custom `fromJson` for private field
If a field is private and the @JsonKey
annotation field fromJson
is set, the serializer ignores this. Here my example model class:
part 'comment.g.dart';
@JsonSerializable()
class Comment {
String comment;
@JsonKey(fromJson: _dateFromJson)
DateTime _commentedAt;
static DateTime _dateFromJson(dynamic date) {
// do something with the date
}
DateTime get commentedAt => _commentedAt;
set commentedAt(DateTime date) => _commentedAt = date;
}
The generated comment.g.dart
looks as follows:
part of 'comment.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
Comment _$CommentFromJson(Map<String, dynamic> json) {
return Comment()
..comment = json['comment'] as String
..commentedAt = json['commentedAt'] == null
? null
: DateTime.parse(json['commentedAt'] as String);
}
Map<String, dynamic> _$CommentToJson(Comment instance) => <String, dynamic>{
'comment': instance.comment,
'commentedAt': instance.commentedAt?.toIso8601String(),
};
But it should look as follows:
part of 'comment.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
Comment _$CommentFromJson(Map<String, dynamic> json) {
return Comment()
..comment = json['comment'] as String
..commentedAt = Comment._dateFromJson(json['commentedAt'])
}
Map<String, dynamic> _$CommentToJson(Comment instance) => <String, dynamic>{
'comment': instance.comment,
'commentedAt': instance.commentedAt?.toIso8601String(),
};
So I have a workaround but I cannot make the field private....
Output of flutter doctor -v
[✓] Flutter (Channel stable, 1.22.6, on Linux, locale en_US.UTF-8)
• Flutter version 1.22.6 at /home/user/tools/flutter
• Framework revision 9b2d32b605 (3 weeks ago), 2021-01-22 14:36:39 -0800
• Engine revision 2f0af37152
• Dart version 2.10.5
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
• Android SDK at /home/user/tools/Android/Sdk
• Platform android-30, build-tools 30.0.2
• ANDROID_HOME = /home/user/tools/Android/Sdk
• Java binary at: /usr/local/android-studio/jre/bin/java
• Java version OpenJDK Runtime Environment (build 1.8.0_212-release-1586-b4-5784211)
• All Android licenses accepted.
[✓] Android Studio (version 3.6)
• Android Studio at /usr/local/android-studio
• Flutter plugin version 49.0.1
• Dart plugin version 192.8052
• Java version OpenJDK Runtime Environment (build 1.8.0_212-release-1586-b4-5784211)
• No issues found!
+1
I'm afraid this is impossible for several reasons. I'll try to sum that up:
- In dart, a method or field of class beginning with
_
is private, this means it is not accessible from outside, so producing aComment._dateFromJson
invocation is not possible. - Since the annotation was placed on the private field
_commentedAt
it's impossible for the generator to map it to another field - Since, I suppose, the default json_serializable settings are on, non annotated field are converted with default converters, hence you find the
DateTime.parse
call.
What you can actually do to achieve what you want is
@JsonSerializable()
class Comment {
Comment({
required this.comment,
required DateTime commentedAt,
}) : _commentedAt = commentedAt;
String comment;
DateTime _commentedAt;
static DateTime dateFromJson(dynamic date) {
// do something with the date
}
@JsonKey(fromJson: dateFromJson)
DateTime get commentedAt => _commentedAt;
set commentedAt(DateTime date) => _commentedAt = date;
}
Which will result in
Comment _$CommentFromJson(Map<String, dynamic> json) => Comment(
comment: json['comment'] as String,
commentedAt: Comment.dateFromJson(json['commentedAt']),
);
@kevmoo Maybe it's time Dart extends their accessory skills beyond 'public-or-private-only' 😉
Duplicate of #569
Trying to align all of these requests into one place!
I have a (draft) PR out on this. I'd LOVE (early) feedback about if this works for what folks need here: https://github.com/google/json_serializable.dart/pull/1256
I still need to do some documentation and testing...