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>
: typeList<dynamic>
is not a subtype of typeList<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>
: typeList<dynamic>
is not a subtype of typeList<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?
- 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
1 Answer
Reset to default 1This 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!