#json #flutter #dart
Вопрос:
У меня есть полезная нагрузка API-ответа с динамическими данными в теле. API возвращает список объектов в data
теге. Я пытаюсь сопоставить ответ с соответствующей моделью во время выполнения, однако при этом я получаю сообщение об ошибке. Как сопоставить объекты динамического ответа во время выполнения без явного создания модели ответа API для каждого из них? В идеале решение должно быть в состоянии определить целевую модель, с которой объект ответа должен быть сопоставлен во время выполнения.
Я получаю следующую ошибку с моим кодом: The argument type 'List<Map<String, dynamic>>' can't be assigned to the parameter type 'Map<String, dynamic>'.
После моей попытки:
return ApiResponse<Team>.fromJson(json.decode(response.body), (data) => Team.fromJson(data) as List<Map<String, dynamic>>);
// Maps the API response to object
class ApiResponse<T> {
int status;
String? message;
T data;
ApiResponse({
required this.status,
this.message,
required this.data,
});
factory ApiResponse.fromJson(Map<String, dynamic> json, Function(List<Map<String, dynamic>>) create) {
return ApiResponse<T>(
status: json['status'],
message: json['message'],
data: create(json['data']),
);
}
}
Мои модели
class User{
int? id;
String? name;
String? description;
DateTime? createdAt;
DateTime? updatedAt;
User({
this.id,
this.name,
this.description,
this.createdAt,
this.updatedAt
});
factory User.fromJson(Map<String, dynamic> json){
return User(
id: json['id'],
name: json['name'],
description: json['description'],
createdAt: DateTime.parse(json['created_at']),
updatedAt: DateTime.parse(json['updated_at']),
);
}
}
class Team {
int id;
String? name;
String? region;
DateTime? createdAt;
DateTime? updatedAt;
Team({
required this.id,
this.name,
this.region,
this.createdAt,
this.updatedAt,
});
factory Team.fromJson(Map<String, dynamic> json){
return Team(
id: json['id'],
name: json['name'],
region: json['region'],
createdAt: DateTime.parse(json['created_at']),
updatedAt: DateTime.parse(json['updated_at']),
);
}
}
Ответ API
{
"status": 200,
"message": "Returned",
"data": [
{
"id": 1,
"name": "Trevo Mgino",
"description": "A Description",
"created_at": "2021-09-29T06:47:03.000000Z",
"updated_at": "2021-09-29T06:47:03.000000Z"
}
],
}
{
"status": 200,
"message": "Activated",
"data": [
{
"id": 1,
"name": "Team A",
"region": "Region 1",
"created_at": "2021-09-29T06:47:03.000000Z",
"updated_at": "2021-09-29T06:47:03.000000Z"
},
{
"id": 2,
"name": "Team B",
"region": "Region 1",
"created_at": "2021-09-29T06:47:03.000000Z",
"updated_at": "2021-09-29T06:47:03.000000Z"
}
],
}
Комментарии:
1. просто расшифруйте свой json и передайте эту команду json.formjson(json)
Ответ №1:
Team.fromJson
принимает a Map<String, dynamic>
в качестве параметров, но вы даете ему a List<Map<String, dynamic>>
.
Я думаю, что вы хотите изменить первое выражение, которое вы дали:
ApiResponse<Team>.fromJson(
json.decode(response.body),
(data) => data.map((teamJson) => Team.fromJson(teamJson)),
)
Кроме того, вы можете ввести безопасный код, который использует ваша фабрика:
class ApiResponse<T> {
int status;
String? message;
T data;
ApiResponse({
required this.status,
this.message,
required this.data,
});
factory ApiResponse.fromJson(
Map<String, dynamic> json,
T Function(List<Map<String, dynamic>>) create,
) {
return ApiResponse<T>(
status: json['status'],
message: json['message'],
data: create(json['data']),
);
}
}
Если вы сделаете это, вам также придется снова изменить свое первое выражение, чтобы написать правильный тип (я думаю, что вы ошиблись, но, возможно, я ошибаюсь).:
ApiResponse<List<Team>>.fromJson(
json.decode(response.body),
(data) => data.map((teamJson) => Team.fromJson(teamJson)).toList(),
);
Ответ №2:
Таким образом, мне удалось решить проблемы со следующим кодом:
// Maps the API response to object
class ApiResponse<T> {
int status;
String? message;
T data;
ApiResponse({
required this.status,
this.message,
required this.data,
});
factory ApiResponse.fromJson(Map<String, dynamic> json, List<T> Function(List<dynamic>) create) {
return ApiResponse<T>(
status: json['status'],
message: json['message'],
data: create(json['data']),
);
}
}
Вызов картографа
return ApiResponse<Team>.fromJson(json.decode(response.body),
(data) => data.map((tData) => Team.fromJson(tData)).toList());