最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

flutter - Disseminate JSON data to freezed data model List<ChildDataModel> through ParentDataModel - Stack Overflo

programmeradmin3浏览0评论

I was trying to disseminate API response to a data model that is specified as List<ChildDataModel> which is nested to a parent data model. Unfortunately, I am confused about why I am encountering an exception.

Currently, I am working with dio, freezed, and riverpod to process API transactions in Flutter.

This is my riverpod setup sample:

@riverpod
Future<ParentDataModel> retrieveApiResponse(
    Ref ref, String endPoint, String functionKey) async {
  final response =
      await dioHelper.retrieveAPIData(endPoint, functionKey);

  developer.log('JSON PROVIDER: ${response.map((data) => data).toList()}');
  return ParentDataModel(
      childDataModel: response
          .map((data) => ChildDataModel.fromJson(data as Map<String, dynamic>))
          .toList() as List<ChildDataModel>);
}

What log prints (beautified example):

[log] JSON PROVIDER:
      [
        {
          "key_id": "CE20-F4CE-232E-3B3D",
          "key_name": "Some value 100"
        },
        {
          "key_id": "C0AC-3U46-1DHC-F432",
          "key_name": "Some value 101"
        },
        {
          "key_id": "26FC-18BB-38DY-10WE",
          "key_name": "Some value 102"
        },
        {
          "key_id": "AGCE-F1QE-1058-11GH",
          "key_name": "Some value 103"
        },
        {
          "key_id": "CE20-B2AF-74AD-47DY",
          "key_name": "Some value 104"
        }
      ]

I have successfully retrieved JSON data and represented it through a widget in Flutter from my API response (without using a data model, but I prefer to use a data model).

The problem is that whenever I tried different code refactoring and research-referenced modifications to this source code.

return ParentDataModel(
      childDataModel: response
          .map((data) => ChildDataModel.fromJson(data as Map<String, dynamic>))
          .toList() as List<ChildDataModel>);

I am eventually getting this exception:

TypeError: Instance of JSArray<dynamic>: type List<dynamic> is not a subtype of type List<ChildDataModel>

This is my freezed data model:

@freezed
class ParentDataModel with _$ParentDataModel {
  factory ParentDataModel({
    String? someField1,
    String? someField2,
    List<ChildDataModel>? childDataModel,
  }) = _ParentDataModel;

  factory ParentDataModel.fromJson(Map<String, dynamic> json) =>
      _$ParentDataModelFromJson(json);
}

@freezed
class ChildDataModel with _$ChildDataModel {
  factory ChildDataModel({
    String? keyID,
    String? keyName,
  }) = _ChildDataModel;

  factory ChildDataModel.fromJson(Map<String, dynamic> json) =>
      _$ChildDataModelFromJson(json);
}

I also tried to refactor this code snippet:

return ParentDataModel(
      childDataModel: response
          .map((data) => ChildDataModel.fromJson(data as Map<String, dynamic>))
          .toList() as List<ChildDataModel>);

into:

return ParentDataModel(
      childDataModel:
          response.map((data) => data).toList() as List<ChildDataModel>);

But I am still encountering the exception...

EDIT: Including the simplified dio method structure

Future<dynamic> retrieveAPIData(
      String endPoint, String function) async {
  final url = Uri.parse('$_baseUrl$endPoint');

  final Map<String, String> plainBodyRequest = {
    _authKey: _authValue,
    'function_key': function,
  };
  final response = await _dio.post(
    url.toString(),
    data: plainBodyRequest,
    options: Options(
      headers: _apiHeaders,
      receiveTimeout: Duration(minutes: 1),
    ),
  );

  return response.data;
}

Which part of the dissemination of JSON data to List<ChildDataModel> introduces the exception, is there any invalid structure in the source code?

I was trying to disseminate API response to a data model that is specified as List<ChildDataModel> which is nested to a parent data model. Unfortunately, I am confused about why I am encountering an exception.

Currently, I am working with dio, freezed, and riverpod to process API transactions in Flutter.

This is my riverpod setup sample:

@riverpod
Future<ParentDataModel> retrieveApiResponse(
    Ref ref, String endPoint, String functionKey) async {
  final response =
      await dioHelper.retrieveAPIData(endPoint, functionKey);

  developer.log('JSON PROVIDER: ${response.map((data) => data).toList()}');
  return ParentDataModel(
      childDataModel: response
          .map((data) => ChildDataModel.fromJson(data as Map<String, dynamic>))
          .toList() as List<ChildDataModel>);
}

What log prints (beautified example):

[log] JSON PROVIDER:
      [
        {
          "key_id": "CE20-F4CE-232E-3B3D",
          "key_name": "Some value 100"
        },
        {
          "key_id": "C0AC-3U46-1DHC-F432",
          "key_name": "Some value 101"
        },
        {
          "key_id": "26FC-18BB-38DY-10WE",
          "key_name": "Some value 102"
        },
        {
          "key_id": "AGCE-F1QE-1058-11GH",
          "key_name": "Some value 103"
        },
        {
          "key_id": "CE20-B2AF-74AD-47DY",
          "key_name": "Some value 104"
        }
      ]

I have successfully retrieved JSON data and represented it through a widget in Flutter from my API response (without using a data model, but I prefer to use a data model).

The problem is that whenever I tried different code refactoring and research-referenced modifications to this source code.

return ParentDataModel(
      childDataModel: response
          .map((data) => ChildDataModel.fromJson(data as Map<String, dynamic>))
          .toList() as List<ChildDataModel>);

I am eventually getting this exception:

TypeError: Instance of JSArray<dynamic>: type List<dynamic> is not a subtype of type List<ChildDataModel>

This is my freezed data model:

@freezed
class ParentDataModel with _$ParentDataModel {
  factory ParentDataModel({
    String? someField1,
    String? someField2,
    List<ChildDataModel>? childDataModel,
  }) = _ParentDataModel;

  factory ParentDataModel.fromJson(Map<String, dynamic> json) =>
      _$ParentDataModelFromJson(json);
}

@freezed
class ChildDataModel with _$ChildDataModel {
  factory ChildDataModel({
    String? keyID,
    String? keyName,
  }) = _ChildDataModel;

  factory ChildDataModel.fromJson(Map<String, dynamic> json) =>
      _$ChildDataModelFromJson(json);
}

I also tried to refactor this code snippet:

return ParentDataModel(
      childDataModel: response
          .map((data) => ChildDataModel.fromJson(data as Map<String, dynamic>))
          .toList() as List<ChildDataModel>);

into:

return ParentDataModel(
      childDataModel:
          response.map((data) => data).toList() as List<ChildDataModel>);

But I am still encountering the exception...

EDIT: Including the simplified dio method structure

Future<dynamic> retrieveAPIData(
      String endPoint, String function) async {
  final url = Uri.parse('$_baseUrl$endPoint');

  final Map<String, String> plainBodyRequest = {
    _authKey: _authValue,
    'function_key': function,
  };
  final response = await _dio.post(
    url.toString(),
    data: plainBodyRequest,
    options: Options(
      headers: _apiHeaders,
      receiveTimeout: Duration(minutes: 1),
    ),
  );

  return response.data;
}

Which part of the dissemination of JSON data to List<ChildDataModel> introduces the exception, is there any invalid structure in the source code?

Share Improve this question edited Feb 14 at 8:10 DarkBee 15.6k8 gold badges72 silver badges116 bronze badges asked Feb 14 at 5:15 DevQtPHDevQtPH 1331 silver badge9 bronze badges 2
  • 1 await dioHelper.retrieveAPIData(endPoint, functionKey); From this line try to make the return already converted to List<ChildDataModel> in this part the childDataModel won't either to identify the response either be empty array or not. – Arbiter Chil Commented Feb 14 at 6:21
  • I found out that there's something to include in the program to properly extract the data from JSON and disseminate it to the data model. I will provide the answer from what I've gone through to resolve the provided issue here. – DevQtPH Commented Feb 14 at 7:15
Add a comment  | 

1 Answer 1

Reset to default 1

This is the solution I've done for the program to run properly, and to suppress the exceptions:

@riverpod
Future<ParentDataModel> retrieveApiResponse(
    Ref ref, String endPoint, String functionKey) async {
  final response =
      await dioHelper.retrieveAPIData(endPoint, functionKey);

  final List responseListData =
      response.map((json) => json).toList() as List<dynamic>;
  final List<ChildDataModel> jsonListData = responseListData
      .map((data) => ChildDataModel.fromJson(data as Map<String, dynamic>))
      .toList();

  return ParentDataModel(childDataModel: jsonListData);
}

I found out that it's a good practice to cast the data variable instance especially when there's a final keyword instance, even if the data is predictable or explicitly represents a data format type.

Here's the good example:

final List responseListData =
      response.map((json) => json).toList() as List<dynamic>;

This solution is best for a simple JSON data format like the given JSON data sample of the question here.

EDIT: Including Clarifications

I am not saying that this solution would work for all setups of dio, freezed, and riverpod. Also, take note that it depends on the structure, correctness, and validity of a JSON data type.


I fot to include that I also updated the ChildDataModel fields, here it is:

UPDATED CODE SNIPPET

@freezed
class ChildDataModel with _$ChildDataModel {
  factory ChildDataModel({
    @JsonKey(name: "key_id") String? keyID,
    @JsonKey(name: "key_name") String? keyName,
  }) = _ChildDataModel;

  factory ChildDataModel.fromJson(Map<String, dynamic> json) =>
      _$ChildDataModelFromJson(json);
}

I hope it helps future readers!

发布评论

评论列表(0)

  1. 暂无评论