2
votes

Impossible de mapper JSON à List dans Dart à l'aide d'un projet Flutter

J'utilisais Flutter 1.0.0 (première version) et récemment mis à jour vers la 1.2.1 et il y avait beaucoup d'erreurs et d'avertissements que j'ai dû corriger. Spécifiant principalement des types d'annotations. Après avoir corrigé tout cela, j'ai exécuté mon application Android et maintenant le code qui mappe JSON à une liste ne fonctionne pas. Je vais d'abord publier mon code original qui a fonctionné. Les données JSON proviennent d'une requête HTTP.

api.dart

return json.decode(response.body).map<Device>((Map<String, dynamic> 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,
      };
}

Maintenant ici C'est là que les problèmes surviennent avec le changement suivant dans 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();
}

Bien que cette syntaxe soit correcte selon Android Studio / Flutter / Dart, il ne semble pas fonctionner. L'application ne plante pas et je n'obtiens pas d'erreurs dans la console d'exécution, elle frappe simplement mon code onError dans mon appel Observable .fromFuture () . p>

J'ai mis des appels print dans mon code pour déterminer que l'instruction de retour dans api.dart était le coupable. Quelqu'un a-t-il un aperçu de ce problème?


2 commentaires

pouvez-vous montrer un exemple de réponse?


Voici les données JSON de la réponse HTTP [{id: 1, name: Pixel, uniqueId: 439610961385665, status: online, phone: 3215551234, model: XL, disabled: false}]


4 Réponses :


1
votes

Je pense qu'au lieu de ceci

  final body = json.decode(response.body).cast<Map<String, dynamic>>();
 return body.map<Device>((json) => Device.fromJson(json)).toList();

vous devriez faire ceci

final body = json.decode(response.body);
  return body.map<Device>((device) => Device.fromJson(device)).toList();


1 commentaires

Le code que vous avez référencé date du moment où j'exécutais Flutter 1.0.0 et ce code fonctionnait. Avec le passage à Flutter 1.2.1, j'ai été obligé de changer mon code et l'instruction de retour vers la fin de la question posée est le code qui ne fonctionne pas. Un autre aperçu?



1
votes

Essayez de cette façon: créez une classe pojo pour les données de réponse.

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');
}
}

créez une méthode pour récupérer des données.

            userDataList = fetchData();

créez maintenant une liste objet comme ceci ..

 Future<UserData> userDataList;

cliquez sur le bouton ..

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');
}
}

vous pouvez également utiliser ce code ci-dessous pour la liste de données ..

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']);
}
}


1 commentaires

Pouvez-vous modifier votre code pour qu'il reflète le mien en renvoyant Future> ?



1
votes

J'ai essayé ce code et il fonctionne, une remarque, votre statut est de type bool mais vous lui donnez une variable de chaîne, soyez conscient de cela. et aussi le json.decode (response.body) vous renverra l'exemple de réponse que j'ai ajouté dans le code, vous n'avez donc pas besoin de le changer. J'espère que cela aidera!

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}");
  }

}


2 commentaires

Pouvez-vous le mapper à un List dans votre boucle for?


Un statut booléen est également attribué à status: json ['status'] == 'online'? vrai: faux,



2
votes

Voici la modification qui résout ce problème.

return json.decode(response.body).map<Device>((dynamic device) => Device.fromJson(device)).toList();


0 commentaires