You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 21:07:25