5

I was running Flutter 1.0.0 (first release) and recently upgraded to 1.2.1 and there were a lot of errors and warnings that I had to correct. Mostly specifying annotation types. After correcting all of these I ran my Android app and now the code that maps JSON to a List is not working. First I'll post my original code that worked. The JSON data is from an HTTP request.

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,
      };
}

Now here is where the issues arises with the following change in api.dart.

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

While this syntax is correct according to Android Studio/Flutter/Dart it doesn't seem to work. The app doesn't crash nor do I get errors in the run console, it just hits my onError code in my Observable<bool>.fromFuture() call.

I put print calls in my code to determine the return statement in api.dart was the culprit. Anyone have any insight into this issue?

2
  • can you show a sample response? Commented Apr 17, 2019 at 4:58
  • This is the JSON data from the HTTP response [{id: 1, name: Pixel, uniqueId: 439610961385665, status: online, phone: 3215551234, model: XL, disabled: false}] Commented Apr 18, 2019 at 19:20

4 Answers 4

4

This is the change that fixes this issue.

return json.decode(response.body).map<Device>((dynamic device) => Device.fromJson(device)).toList();
Sign up to request clarification or add additional context in comments.

Comments

2

Try this way make pojo class for response data..

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 method for fetch data..

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

now make list object like this way..

 Future<UserData> userDataList;

click on button..

            userDataList = fetchData();

you can also used this below code for list of data..

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 Comment

Can you modify your code so it reflects mine in that it would return Future<List<UserData>>?
1

I think instead of this

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

you should do this

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

1 Comment

The code you referenced is from when I was running Flutter 1.0.0 and that code worked. With me moving to Flutter 1.2.1 I was forced to change my code and the return statement towards the end of the posted question is the code that isn't working. Any further insight?
1

I tried this code and it is working, one side note, your status is of type bool but you are giving it a string variable, be aware about that. and also the json.decode(response.body) will return to you the sample response i added in the code, so you don't need to change it. Hope it helps!

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 Comments

Can you map it to a List<Device> in your for loop?
Also status is assigned a bool status: json['status'] == 'online' ? true : false,

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.