Flutter - 如何使用泛型将嵌套的json解析为类?

Seb*_*ian 8 generics parsing json dart flutter

我想知道如何将嵌套的json解析为具有泛型类型的类.我的目的是将来自后端的响应(如包含令牌的loginRespose)与代码和消息包装起来

我有

class BaseResponse<T>{
  int code;
  String message;
  T responseObject;

  BaseResponse.fromJson(Map<String, dynamic> parsedJson)
    : code = parsedJson['Code'],
      message = parsedJson['Message'],
      responseObject = T.fromJson(parsedJson['ResponseObject']); //This is what I'd like to do
}
Run Code Online (Sandbox Code Playgroud)

显然,最后一行会抛出错误,因为T没有命名构造函数"fromJson".我尝试为Type添加一些限制,但我找不到任何解决方案.你知道如何解决这个问题吗?

Rém*_*let 9

你做不到这样的事情,至少不是在颤抖.由于dart:mirror禁用,并且类构造函数没有接口.

你必须采取不同的路线.

我建议改用POO.你会放弃responseObject你的反序列化BaseResponse.然后有子类来BaseResponse处理这个反序列化

通常,每种类型都有一个子类:

class IntResponse extends BaseResponse<int> {
  IntResponse.fromJson(Map<String, dynamic> json) : super._fromJson(json) {
    this.responseObject = int.parse(json["Hello"]);
  }
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以通过添加自定义工厂构造函数BaseResponse来隐藏此混乱,以使其更方便使用.

class BaseResponse<T> {
  int code;
  String message;
  T responseObject;

  BaseResponse._fromJson(Map<String, dynamic> parsedJson)
      : code = parsedJson['Code'],
        message = parsedJson['Message'];

  factory BaseResponse.fromJson(Map<String, dynamic> json) {
    if (T == int) {
      return IntResponse.fromJson(json) as BaseResponse<T>;
    }
    throw UnimplementedError();
  }
}
Run Code Online (Sandbox Code Playgroud)

然后直接实例化想要的类型,或使用工厂构造函数:

final BaseResponse foo = BaseResponse.fromJson<int>({"Hello": "42", "Code": 42, "Message": "World"});
Run Code Online (Sandbox Code Playgroud)

  • 如果“T”像“List&lt;int&gt;”一样嵌套会怎样? (3认同)

Car*_*mer 5

您可以使用built_value包来实现此目的(您还需要built_value_generatorbuild_runner)。你的类看起来像这样:

part 'base_response.g.dart';

abstract class BaseResponse<T> implements Built<BaseResponse<T>, BaseResponseBuilder<T>> {
  int code;
  String message;
  T responseObject;

  factory BaseResponse([updates(BaseResponseBuilder<T> b)]) = _$BaseResponse<T>;

  static Serializer<BaseResponse> get serializer => _$baseResponseSerializer;
}
Run Code Online (Sandbox Code Playgroud)

您必须运行flutter packages pub run build_runner build才能生成生成的文件。然后你像这样使用它:

BaseResponse baseResponse = serializers.deserialize(
  json.decode(response.body),
  specifiedType: const FullType(BaseResponse, const [FullType(ConcreteTypeGoesHere)])
);
Run Code Online (Sandbox Code Playgroud)

您还需要处理一点样板文件。您需要另一个名为serializers.dart 的文件。您需要在此处手动添加要反序列化的所有类,以及为每个采用类型参数的类以及您要使用的每个具体类型添加一个 addBuilderFactory 函数。

part 'serializers.g.dart';

@SerializersFor(const [
  BaseResponse,
  ConcreteTypeGoesHere,
])
final Serializers serializers = (_$serializers.toBuilder()
      ..addBuilderFactory(
        FullType(BaseResponse, const [const FullType(ConcreteTypeGoesHere)]),
        () => new BaseResponseBuilder<ConcreteTypeGoesHere>()
      )
      ..addPlugin(StandardJsonPlugin()))
    .build();
Run Code Online (Sandbox Code Playgroud)

然后重新运行flutter packages pub run build_runner build

让我希望 Gson...:S