Search code examples
arraysjsonflutterdartnsjsonserialization

Dart List<dynamic> Can't Convert In To List<MyModel>


I am a React JS / native developer that trying to learn Flutter. This is an example object from my external API.

[
   {
      "place_id":224809725,
      "licence":"Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright",
      "osm_type":"node",
      "osm_id":637895939,
      "boundingbox":[
         "6.5834343",
         "6.6634343",
         "80.5031464",
         "80.5831464"
      ],
      "lat":"6.6234343",
      "lon":"80.5431464",
      "display_name":"Pelmadulla, Ratnapura District, Sabaragamuwa Province, 70070, Sri Lanka",
      "class":"place",
      "type":"town",
      "importance":0.41001
   }
]

So now I have created this Model Class to Manipulate my data.

class AddressModel {
  int placeId;
  double lat;
  double lon;
  String displayName;
  AddressModel({
    required this.placeId,
    required this.lat,
    required this.lon,
    required this.displayName,
  });

  factory AddressModel.fromMap(Map<String, dynamic> map) {
    return AddressModel(
      placeId: map['placeId']?.toInt() ?? 0,
      lat: map['lat']?.toDouble() ?? 0.0,
      lon: map['lon']?.toDouble() ?? 0.0,
      displayName: map['displayName'] ?? '',
    );
  }

  AddressModel copyWith({
    int? placeId,
    double? lat,
    double? lon,
    String? displayName,
  }) {
    return AddressModel(
      placeId: placeId ?? this.placeId,
      lat: lat ?? this.lat,
      lon: lon ?? this.lon,
      displayName: displayName ?? this.displayName,
    );
  }

  Map<String, dynamic> toMap() {
    final result = <String, dynamic>{};

    result.addAll({'placeId': placeId});
    result.addAll({'lat': lat});
    result.addAll({'lon': lon});
    result.addAll({'displayName': displayName});

    return result;
  }

  String toJson() => json.encode(toMap());

  factory AddressModel.fromJson(String source) =>
      AddressModel.fromMap(json.decode(source));

  @override
  String toString() {
    return 'AddressModel(placeId: $placeId, lat: $lat, lon: $lon, displayName: $displayName)';
  }

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;

    return other is AddressModel &&
        other.placeId == placeId &&
        other.lat == lat &&
        other.lon == lon &&
        other.displayName == displayName;
  }

  @override
  int get hashCode {
    return placeId.hashCode ^
        lat.hashCode ^
        lon.hashCode ^
        displayName.hashCode;
  }
}

So after making an HTTP request, I get data from my API. So not I need to store this data in my redux store. (I use flutter redux) But my expected data type is AddressModel So I convert my data like this.

  final List addressList = json.decode(response.body);
  List<AddressModel> addresses = addressList.map((e) {
    AddressModel addressModel = AddressModel.fromMap(e);
    return addressModel;
  }).toList();

But after I print my addresses it's not printing. addressList is printing my expected values. I have been trying to find out what went wrong from my end for hours. But I can't. Coz my code looks okay to me. Can anyone help me with this, please?


Solution

  • Here are the things that need to be fixed:

    • In Dart, parsing a String is done by calling the parse or tryParse method of the expected num type. For example, you can do int.parse('2') or double.parse('3.0').
    • The json keys are in snake_case, so you need to keep the snake_case when accessing the key from the json map. Replace map['placeId'] to map['place_id'] and map['displayName'] to map['display_name'].
    • There is no need to parse place_id because it's already a number in the json.

    So the AddressModel.fromMap factory constructor should be like this:

    factory AddressModel.fromMap(Map<String, dynamic> map) {
      return AddressModel(
        placeId: map['place_id'] ?? 0,
        lat: double.tryParse(map['lat']) ?? 0.0,
        lon: double.tryParse(map['lon']) ?? 0.0,
        displayName: map['display_name'] ?? '',
      );
    }