Home > Software design >  Adding Map elements into List in Dart
Adding Map elements into List in Dart

Time:03-29

I have a JSON response that is of type Map<String, dynamic> out of which I would like to extract elements into a List. I would like to know how this can be done. I have written a piece of code for that which doesn't really work and throws the error you will see below. I'm welcome to suggestions of all kinds. Below are the code, error and the JSON response:

JSON Response(I'm only interested in getting the values of the key(list) named data)

{
    "status": "200",
    "data": {
        "current_page": 1,
        "data": [                     //I need the values in this list
            {
                "restaurant_id": 1,
                "restaurant_name": "City Club",
                "restaurant_address": "Street Number 17, GN Block, Sector V, Bidhannagar, Kolkata, West Bengal 700091",
                "restaurant_image": "/public/assets/restaurant/6x4aJL03-36-30.jpg",
                "restaurant_rating": "4",
                "restaurant_rating_count": "8",
                "distance": 0
            },
            {
                "restaurant_id": 6,
                "restaurant_name": "Mocambo",
                "restaurant_address": "Ground Floor, 25B, Mirza Ghalib St, Taltala, Kolkata, West Bengal 700016",
                "restaurant_image": "/public/assets/restaurant/A6lAQu03-41-17.jpg",
                "restaurant_rating": null,
                "restaurant_rating_count": null,
                "distance": 14.8039003284490693346242551342584192752838134765625
            },
            {
                "restaurant_id": 7,
                "restaurant_name": "Peter Cat",
                "restaurant_address": "Park St, opposite KFC Restaurant, Park Street area, Kolkata, West Bengal 700016",
                "restaurant_image": "/public/assets/restaurant/RfjxvK03-44-59.jpg",
                "restaurant_rating": null,
                "restaurant_rating_count": null,
                "distance": 47.4211446933120015501117450185120105743408203125
            },
            {
                "restaurant_id": 8,
                "restaurant_name": "Flurrys",
                "restaurant_address": "Grand Trunk Rd, Barabazar, Sukhsanatantala, Chandannagar, West Bengal 712136",
                "restaurant_image": "/public/assets/restaurant/Pitmxq03-47-20.jpg",
                "restaurant_rating": null,
                "restaurant_rating_count": null,
                "distance": 116.161207301201244490584940649569034576416015625
            },
            {
                "restaurant_id": 9,
                "restaurant_name": "Karims",
                "restaurant_address": "GP Block, Sector V, Bidhannagar, Kolkata, West Bengal 700091",
                "restaurant_image": "/public/assets/restaurant/brmWnW03-51-13.jpg",
                "restaurant_rating": null,
                "restaurant_rating_count": null,
                "distance": 179.675331121963466785018681548535823822021484375
            }
        ],
        "first_page_url": "https://achievexsolutions.in/current_work/eatiano/api/all_restaurant?page=1",
        "from": 1,
        "last_page": 1,
        "last_page_url": "https://achievexsolutions.in/current_work/eatiano/api/all_restaurant?page=1",
        "links": [
            {
                "url": null,
                "label": "&laquo; Previous",
                "active": false
            },
            {
                "url": "https://achievexsolutions.in/current_work/eatiano/api/all_restaurant?page=1",
                "label": "1",
                "active": true
            },
            {
                "url": null,
                "label": "Next &raquo;",
                "active": false
            }
        ],
        "next_page_url": null,
        "path": "https://achievexsolutions.in/current_work/eatiano/api/all_restaurant",
        "per_page": 25,
        "prev_page_url": null,
        "to": 5,
        "total": 5
    }
}

The code that I've written:

class PopularRestaurantProvider with ChangeNotifier {
  String baseUrl = 'baseUrl';
  Map<String, dynamic> _restaurants = {};
  List<dynamic> _restaurantList = [];
  final queryParams = {'lat': '22.5735314', 'lng': '88.4331189'};

  Map<String, dynamic> get restaurants {
    return {..._restaurants};
  }

  List<dynamic> get restaurantList {
    return [..._restaurantList];
  }

  Future<void> fetchRestaurants() async {
    final url = Uri.parse(baseUrl  
        'api/all_restaurant'  
        '?'  
        'lat=${queryParams['lat']}'  
        '&'  
        'lng=${queryParams['lng']}');
    final response = await http.get(url);
    PopularRestaurants popularRestaurants =
        popularRestaurantsFromJson(response.body);
    _restaurants = popularRestaurants.toJson();
    _restaurants['data']['data'].forEach((key, value) => _restaurantList.add(value));   //This is where I've tried adding the elements 
    print('Restaurants List $_restaurantList');     //Currently this doesn't print anything
  }
}

The model class that I have generated out of the response:

PopularRestaurants popularRestaurantsFromJson(String str) =>
    PopularRestaurants.fromJson(json.decode(str));

String popularRestaurantsToJson(PopularRestaurants data) =>
    json.encode(data.toJson());

class PopularRestaurants {
  PopularRestaurants({
    required this.status,
    required this.data,
  });

  String status;
  Data data;

  factory PopularRestaurants.fromJson(Map<String, dynamic> json) =>
      PopularRestaurants(
        status: json["status"],
        data: Data.fromJson(json["data"]),
      );

  Map<String, dynamic> toJson() => {
        "status": status,
        "data": data.toJson(),
      };
}

class Data {
  Data({
    required this.currentPage,
    required this.data,
    required this.firstPageUrl,
    required this.from,
    required this.lastPage,
    required this.lastPageUrl,
    required this.links,
    required this.nextPageUrl,
    required this.path,
    required this.perPage,
    required this.prevPageUrl,
    required this.to,
    required this.total,
  });

  int currentPage;
  List<Datum> data;
  String firstPageUrl;
  int from;
  int lastPage;
  String lastPageUrl;
  List<Link> links;
  dynamic nextPageUrl;
  String path;
  int perPage;
  dynamic prevPageUrl;
  int to;
  int total;

  factory Data.fromJson(Map<String, dynamic> json) => Data(
        currentPage: json["current_page"],
        data: List<Datum>.from(json["data"].map((x) => Datum.fromJson(x))),
        firstPageUrl: json["first_page_url"],
        from: json["from"],
        lastPage: json["last_page"],
        lastPageUrl: json["last_page_url"],
        links: List<Link>.from(json["links"].map((x) => Link.fromJson(x))),
        nextPageUrl: json["next_page_url"],
        path: json["path"],
        perPage: json["per_page"],
        prevPageUrl: json["prev_page_url"],
        to: json["to"],
        total: json["total"],
      );

  Map<String, dynamic> toJson() => {
        "current_page": currentPage,
        "data": List<dynamic>.from(data.map((x) => x.toJson())),
        "first_page_url": firstPageUrl,
        "from": from,
        "last_page": lastPage,
        "last_page_url": lastPageUrl,
        "links": List<dynamic>.from(links.map((x) => x.toJson())),
        "next_page_url": nextPageUrl,
        "path": path,
        "per_page": perPage,
        "prev_page_url": prevPageUrl,
        "to": to,
        "total": total,
      };
}

class Datum {
  Datum({
    required this.restaurantId,
    required this.restaurantName,
    required this.restaurantAddress,
    required this.restaurantImage,
    required this.restaurantRating,
    required this.restaurantRatingCount,
    required this.distance,
  });

  int restaurantId;
  String restaurantName;
  String restaurantAddress;
  String restaurantImage;
  dynamic restaurantRating;
  dynamic restaurantRatingCount;
  double distance;

  factory Datum.fromJson(Map<String, dynamic> json) => Datum(
        restaurantId: json["restaurant_id"],
        restaurantName: json["restaurant_name"],
        restaurantAddress: json["restaurant_address"],
        restaurantImage: json["restaurant_image"],
        restaurantRating: json["restaurant_rating"],
        restaurantRatingCount: json["restaurant_rating_count"],
        distance: json["distance"].toDouble(),
      );

  Map<String, dynamic> toJson() => {
        "restaurant_id": restaurantId,
        "restaurant_name": restaurantName,
        "restaurant_address": restaurantAddress,
        "restaurant_image": restaurantImage,
        "restaurant_rating": restaurantRating,
        "restaurant_rating_count": restaurantRatingCount,
        "distance": distance,
      };
}

class Link {
  Link({
    required this.url,
    required this.label,
    required this.active,
  });

  String url;
  String label;
  bool active;

  factory Link.fromJson(Map<String, dynamic> json) => Link(
        url: json["url"] == null ? null : json["url"],
        label: json["label"],
        active: json["active"],
      );

  Map<String, dynamic> toJson() => {
        "url": url == null ? null : url,
        "label": label,
        "active": active,
      };
}

The error I get at the moment:

Unhandled Exception: type '(dynamic) => dynamic' is not a subtype of type '(String, dynamic) => MapEntry<dynamic, dynamic>' of 'transform

CodePudding user response:

_restaurants['data']['data'] is a List of Map so the code should be like this:

for(var item in _restaurants['data']['data']) {
   item.forEach((key, value) => _restaurantList.add(value));
}

CodePudding user response:

@Belinda is correct in that _restaurants['data']['data'] is a List.

This is why your line here returns an error because the List itself doesn't have any keys or values.

_restaurants['data']['data'].forEach((key, value) => _restaurantList.add(value));   //This is where I've tried adding the elements 

However, that solution will populate one big list with a mix of all the individual keys of each Map with no separation. Maybe that is in fact what you want, but my understanding from your question is that you wanted a list of the maps inside of _restaurants['data']['data'].

If that is the case you can simply do this instead of the line quoted above.

_restaurantList = _restaurants['data']['data'] as List;

Which will print this and you can access each index in the List as an individual Map.

Restaurants List [{restaurant_id: 1, restaurant_name: City Club, restaurant_address: Street Number 17, GN Block, Sector V, Bidhannagar, Kolkata, West Bengal 700091, restaurant_image: /public/assets/restaurant/6x4aJL03-36-30.jpg, restaurant_rating: 4, restaurant_rating_count: 8, distance: 0.0}, {restaurant_id: 6, restaurant_name: Mocambo, restaurant_address: Ground Floor, 25B, Mirza Ghalib St, Taltala, Kolkata, West Bengal 700016, restaurant_image: /public/assets/restaurant/A6lAQu03-41-17.jpg, restaurant_rating: null, restaurant_rating_count: null, distance: 14.80390032844907}, {restaurant_id: 7, restaurant_name: Peter Cat, restaurant_address: Park St, opposite KFC Restaurant, Park Street area, Kolkata, West Bengal 700016, restaurant_image: /public/assets/restaurant/RfjxvK03-44-59.jpg, restaurant_rating: null, restaurant_rating_count: null, distance: 47.421144693312}, {restaurant_id: 8, restaurant_name: Flurrys, restaurant_address: Grand Trunk Rd, Barabazar, Sukhsanatantala, Chandannaga<…>
  • Related