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

时间:2018-07-28 21:22:37

标签: json parsing generics 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
}

很显然,最后一行引发错误,因为T没有命名构造函数“ fromJson”。 我尝试为Type添加一些限制,但是没有找到任何解决方案。您对如何实现此目标有任何想法吗?

2 个答案:

答案 0 :(得分:7)

您不能做这种事情,至少不能动摇。由于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"]);
  }
}

然后您可以通过在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();
  }
}

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

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

答案 1 :(得分:2)

您可以使用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;
}

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

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

您只需要注意一点点样板即可。您需要另一个名为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();

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

让我对Gson充满希望...:S