#json #dart #flutter
#json #dart #трепетание
Вопрос:
Я запускал Flutter 1.0.0 (первый выпуск) и недавно обновился до 1.2.1, и было много ошибок и предупреждений, которые мне пришлось исправить. В основном, указывая типы аннотаций. После исправления всего этого я запустил свое приложение для Android, и теперь код, который сопоставляет JSON со списком, не работает. Сначала я опубликую свой оригинальный код, который сработал. Данные JSON получены из HTTP-запроса.
api.dart
Future<List<Device>> getDevices() async {
var response = await _httpNetwork.get(_devicesUrl, headers: {"Cookie": _sessionId});
if (response.statusCode < 200 || response.statusCode > 400) {
throw Exception("Error while fetching data");
}
final body = json.decode(response.body);
return body.map<Device>((device) => Device.fromJson(device)).toList();
}
device.dart
class Device {
Device({
this.id,
this.name,
this.uniqueId,
this.status,
this.phone,
this.model,
this.disabled,
});
factory Device.fromJson(Map<String, dynamic> json) => Device(
id: json['id'],
name: json['name'],
uniqueId: json['uniqueId'],
status: json['status'] == 'online' ? true : false,
phone: json['phone'],
model: json['model'],
disabled: json['disabled'],
);
// API data
int id;
String name;
String uniqueId;
bool status;
String phone;
String model;
bool disabled;
Map<String, dynamic> toJson() => <String, dynamic>{
'id': id,
'name': name,
'uniqueId': uniqueId,
'status': status == true ? 'online' : 'offline',
'phone': phone,
'model': model,
'disabled': disabled,
};
}
Теперь вот где возникают проблемы со следующим изменением api.dart
.
return json.decode(response.body).map<Device>((Map<String, dynamic> device) => Device.fromJson(device)).toList();
Хотя этот синтаксис верен в соответствии с Android Studio / Flutter / Dart, похоже, он не работает. Приложение не выходит из строя, и я не получаю ошибок в консоли запуска, оно просто попадает в мой onError
код при моем Observable<bool>.fromFuture()
вызове.
Я вставил print
вызовы в свой код, чтобы определить, что оператор return в api.dart
был виновником. У кого-нибудь есть представление об этой проблеме?
Комментарии:
1. можете ли вы показать пример ответа?
2. Это данные JSON из HTTP-ответа
[{id: 1, name: Pixel, uniqueId: 439610961385665, status: online, phone: 3215551234, model: XL, disabled: false}]
Ответ №1:
Попробуйте таким образом создать класс pojo для данных ответа..
class UserData {
final int albumId;
final int id;
final String title;
final String url;
final String thumbnailUrl;
UserData({this.albumId, this.id, this.title, this.url, this.thumbnailUrl});
factory UserData.fromJson(Map<String, dynamic> json) {
return new UserData(
albumId: json['albumId'],
id: json['id'],
title: json['title'],
url: json['url'],
thumbnailUrl: json['thumbnailUrl']);
}
}
метод make для выборки данных..
Future<UserData> fetchData() async {
var result = await get('https://jsonplaceholder.typicode.com/photos');
if (result.statusCode == 200) {
return UserData.fromJson(json.decode(result.body));
} else {
// If that response was not OK, throw an error.
throw Exception('Failed to load post');
}
}
теперь создайте объект list следующим образом..
Future<UserData> userDataList;
нажмите на кнопку..
userDataList = fetchData();
вы также можете использовать приведенный ниже код для списка данных..
List<UserData> list = List();
var isLoading = false;
void fetchData() async {
setState(() {
isLoading = true;
});
final response = await get("https://jsonplaceholder.typicode.com/photos");
if (response.statusCode == 200) {
list = (json.decode(response.body) as List)
.map((data) => UserData.fromJson(data))
.toList();
setState(() {
isLoading = false;
});
} else {
throw Exception('Failed to load photos');
}
}
Комментарии:
1. Можете ли вы изменить свой код так, чтобы он отражал мой, чтобы он возвращался
Future<List<UserData>>
?
Ответ №2:
Это изменение, которое устраняет эту проблему.
return json.decode(response.body).map<Device>((dynamic device) => Device.fromJson(device)).toList();
Ответ №3:
Я думаю, что вместо этого
final body = json.decode(response.body);
return body.map<Device>((device) => Device.fromJson(device)).toList();
вы должны сделать это
final body = json.decode(response.body).cast<Map<String, dynamic>>();
return body.map<Device>((json) => Device.fromJson(json)).toList();
Комментарии:
1. Код, на который вы ссылались, взят из того времени, когда я запускал Flutter 1.0.0, и этот код работал. Когда я перешел на Flutter 1.2.1, я был вынужден изменить свой код, и оператор return в конце опубликованного вопроса — это код, который не работает. Есть еще какие-нибудь идеи?
Ответ №4:
Я попробовал этот код, и он работает, с одной стороны, у вас status
есть тип bool
, но вы даете ему строковую переменную, имейте это в виду. а также json.decode(response.body)
вернет вам пример ответа, который я добавил в код, так что вам не нужно его менять. Надеюсь, это поможет!
class Device {
Device({
this.id,
this.name,
this.uniqueId,
this.status,
this.phone,
this.model,
this.disabled,
});
factory Device.fromJson(Map<String, dynamic> json) => Device(
id: json['id'],
name: json['name'],
uniqueId: json['uniqueId'],
status: json['status'] == 'online' ? true : false,
phone: json['phone'],
model: json['model'],
disabled: json['disabled'],
);
// API data
int id;
String name;
String uniqueId;
bool status;
String phone;
String model;
bool disabled;
Map<String, dynamic> toJson() => <String, dynamic>{
'id': id,
'name': name,
'uniqueId': uniqueId,
'status': status == true ? 'online' : 'offline',
'phone': phone,
'model': model,
'disabled': disabled,
};
}
void main() {
var resp = [{"id": 1, "name": "Pixel", "uniqueId": "439610961385665",
"status": "online", "phone": "3215551234", "model": "XL", "disabled": false}];
List json = resp;
for(var item in json){
Device device = Device.fromJson(item);
print("nameDevice: ${device.status}");
}
}
Комментарии:
1. Можете ли вы сопоставить его с a
List<Device>
в вашем цикле for?2. Также статусу присваивается bool
status: json['status'] == 'online' ? true : false,