如何让Freezed框架正确识别@JsonKey注解?
解决Freezed框架中@JsonKey(name: '_id')注解不生效的问题
问题说明
使用Freezed定义Token类时,为id字段添加@JsonKey(name: '_id')注解,期望序列化时该字段名为_id,但调用toJson()后(或打印类实例时)未得到预期结果:
原代码
import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:mongo_dart/mongo_dart.dart'; import 'package:myapp_shared/src/converters/datetime_converter.dart'; import 'package:myapp_shared/src/converters/object_id_converter.dart'; part 'token.freezed.dart'; part 'token.g.dart'; @freezed class Token with _$Token { @JsonSerializable( fieldRename: FieldRename.snake, explicitToJson: true, ) const factory Token({ @ObjectIdConverter() @JsonKey(name: '_id') ObjectId? id, @ObjectIdConverter() ObjectId? workSpace, @ObjectIdConverter() ObjectId? ownerId, String? ownerEmail, String? token, Map<String, dynamic>? data, String? reason, String? description, bool? deleted, @DateTimeConverter() DateTime? deletedAt, @DateTimeConverter() DateTime? expireAt, int? numberOfUpdates, @DateTimeConverter() DateTime? createdAt, @DateTimeConverter() DateTime? updatedAt, }) = _Token; factory Token.fromJson(Map<String, dynamic> json) => _$TokenFromJson(json); }
实际输出(toString调试结果)
Token(id: ObjectId("6792fbdfb028427079000000"), ownerId: null, ownerEmail: xxx@gmail.com, ...)
期望的JSON序列化结果
{ "_id": "6792fbdfb028427079000000", "owner_email": "xxx@gmail.com", ... }
解决方案
1. 澄清概念:toString与toJson的区别
你展示的Token(id: ...)是Freezed类的toString调试输出,它显示的是Dart类的原始字段名id,而非JSON序列化后的键名。真正的toJson()输出才会使用@JsonKey指定的_id,可以通过打印token.toJson()来验证。
2. 确保注解配置正确并重新生成代码
调整注解顺序(推荐)
将@JsonKey放在转换器注解之前,避免潜在的注解优先级问题:
@JsonKey(name: '_id') @ObjectIdConverter() ObjectId? id,
重新生成序列化代码
修改注解后,必须运行build_runner命令重新生成.g.dart和.freezed.dart文件,否则修改不会生效:
# Flutter项目 flutter pub run build_runner build --delete-conflicting-outputs # Dart纯项目 dart run build_runner build --delete-conflicting-outputs
3. 验证结果
调用toJson()后,打印结果应包含_id键:
final token = Token(id: ObjectId(), ownerEmail: "xxx@gmail.com"); print(token.toJson()); // 输出示例:{"_id": "6792fbdfb028427079000000", "owner_email": "xxx@gmail.com", ...}
4. (可选)自定义toString输出
如果希望调试时的toString也显示_id,可以在类中添加自定义toString方法:
@freezed class Token with _$Token { // ... 原factory代码 ... factory Token.fromJson(Map<String, dynamic> json) => _$TokenFromJson(json); // 自定义toString String toString() { return "Token(_id: ${id}, ownerId: ${ownerId}, ownerEmail: ${ownerEmail}, ...)"; } }
内容的提问来源于stack exchange,提问作者ololo
相关产品推荐
相关产品推荐

