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

如何结合泛型最佳使用json_serializable?支持嵌套泛型场景

解决泛型Response类支持深层嵌套类型的Json序列化问题

我完全理解你的需求——想要一个通用的Response<T>类,既能用json_serializable快速序列化,又能完美支持T从原生类型到多层嵌套泛型自定义类的所有场景。之前用自定义类型转换器搞不定深层嵌套的问题,其实是因为普通转换器没法递归处理泛型参数的嵌套逻辑,不过我们可以通过json_serializable的泛型参数工厂特性来解决这个问题,哪怕需要写一些上层封装代码也完全能实现完美支持。

第一步:配置泛型Response类,开启genericArgumentFactories

首先修改你的Response类,开启genericArgumentFactories参数,这个参数会让生成的序列化方法接收一个处理T类型的转换函数,从而支持递归处理嵌套类型:

import 'package:json_annotation/json_annotation.dart';

part 'response.g.dart';

@JsonSerializable(genericArgumentFactories: true)
class Response<T> {
  final int code;
  final T data;

  Response({required this.code, required this.data});

  // 新增泛型转换函数参数fromJsonT,用来处理T的反序列化
  factory Response.fromJson(
    Map<String, dynamic> json,
    T Function(Object? json) fromJsonT,
  ) =>
      _$ResponseFromJson(json, fromJsonT);

  // 新增泛型转换函数参数toJsonT,用来处理T的序列化
  Map<String, dynamic> toJson(
    Object? Function(T value) toJsonT,
  ) =>
      _$ResponseToJson(this, toJsonT);
}

第二步:针对具体的T类型,传入对应的转换逻辑

不管T是原生类型、自定义类还是深层嵌套的泛型类,只需要在调用fromJson/toJson时传入对应的转换函数即可。

举几个常见场景的例子:

场景1:T是自定义普通类(比如User)

先定义你的自定义类并配置序列化:

import 'package:json_annotation/json_annotation.dart';

part 'user.g.dart';

@JsonSerializable()
class User {
  final String name;
  final int age;

  User({required this.name, required this.age});

  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
  Map<String, dynamic> toJson() => _$UserToJson(this);
}

然后反序列化Response<User>:

final jsonMap = {'code': 200, 'data': {'name': 'Alice', 'age': 30}};
final userResponse = Response.fromJson(
  jsonMap,
  (json) => User.fromJson(json as Map<String, dynamic>),
);

场景2:T是嵌套的泛型集合(比如List)

final listJson = {'code': 200, 'data': [
  {'name': 'Alice', 'age': 30},
  {'name': 'Bob', 'age': 25}
]};
final userListResponse = Response.fromJson(
  listJson,
  (json) => (json as List).map((item) => User.fromJson(item as Map<String, dynamic>)).toList(),
);

场景3:T是多层嵌套的泛型类(比如Result)

先定义嵌套的泛型类同样开启genericArgumentFactories:

import 'package:json_annotation/json_annotation.dart';

part 'result.g.dart';

@JsonSerializable(genericArgumentFactories: true)
class Result<U> {
  final U value;
  final String message;

  Result({required this.value, required this.message});

  factory Result.fromJson(
    Map<String, dynamic> json,
    U Function(Object? json) fromJsonU,
  ) =>
      _$ResultFromJson(json, fromJsonU);

  Map<String, dynamic> toJson(
    Object? Function(U value) toJsonU,
  ) =>
      _$ResultToJson(this, toJsonU);
}

然后反序列化Response<Result<User>>:

final nestedJson = {'code': 200, 'data': {
  'value': {'name': 'Alice', 'age': 30},
  'message': '请求成功'
}};
final nestedResponse = Response.fromJson(
  nestedJson,
  (json) => Result.fromJson(
    json as Map<String, dynamic>,
    (userJson) => User.fromJson(userJson as Map<String, dynamic>),
  ),
);

第三步:封装上层代码简化调用(可选)

如果觉得每次都写转换函数太繁琐,可以封装扩展方法或者工厂类来简化调用:

extension ResponseHelpers on Response {
  // 封装User类型的Response反序列化
  static Response<User> fromUserJson(Map<String, dynamic> json) {
    return Response.fromJson(json, (json) => User.fromJson(json as Map<String, dynamic>));
  }

  // 封装List<User>类型的Response反序列化
  static Response<List<User>> fromUserListJson(Map<String, dynamic> json) {
    return Response.fromJson(
      json,
      (json) => (json as List).map((item) => User.fromJson(item as Map<String, dynamic>)).toList(),
    );
  }

  // 封装Result<User>类型的Response反序列化
  static Response<Result<User>> fromNestedUserResultJson(Map<String, dynamic> json) {
    return Response.fromJson(
      json,
      (json) => Result.fromJson(
        json as Map<String, dynamic>,
        (userJson) => User.fromJson(userJson as Map<String, dynamic>),
      ),
    );
  }
}

调用时就可以直接用:

final userResponse = ResponseHelpers.fromUserJson(jsonMap);

为什么之前的自定义转换器不行?

普通的JsonConverter是针对单一固定类型设计的,没法动态处理泛型参数的深层嵌套逻辑。而开启genericArgumentFactories后,生成的序列化代码会把T的转换逻辑完全委托给你传入的函数,这个函数可以递归处理任意层级的嵌套泛型,完美解决你的问题。

最后别忘了运行build_runner生成序列化代码:

# Flutter项目
flutter pub run build_runner build

# 纯Dart项目
dart run build_runner build

内容的提问来源于stack exchange,提问作者user7720975

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 09:27:37