Home > Blockchain >  Unhandled Exception: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype
Unhandled Exception: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype

Time:12-31

I am trying to fetch data from a local json file in my assets. I received and decoded data and then tried to store it in a list for further use. But it give me the exception. I want the list to be of type OriginDestination, store it in database and then use it further. Can someone please tell me how can I parse data from json to OriginDestination.

Class OriginDestination -

OriginDestination cityDtoFromJson(String str) => OriginDestination.fromJson(json.decode(str));

String cityDtoToJson(OriginDestination data) => json.encode(data.toJson());

@HiveType(typeId: 0)
// ignore: non_constant_identifier_names
class OriginDestination extends HiveObject {

  @HiveField(0)
  City? origin;

  @HiveField(1)
  List<City>? destinations;

  OriginDestination({
    this.origin,
    this.destinations,
  });

  factory OriginDestination.fromJson(Map<String, dynamic> json) => OriginDestination(
    origin: City.fromJson(json["origin"]),
    destinations: List<City>.from(
        json["destinations"].map((x) => City.fromJson(x))),
  );

  Map<String, dynamic> toJson() => {
    "origin": origin,
    "destinations": destinations,
  };

Code where I am fetching data and want to use it (originDestinations is also a list of type OriginDestination) -

List<OriginDestination>? localOriginDestination = [];

  Future<void> readJson() async {
    final String response = await rootBundle.loadString('assets/files/node.json');
    final data = await json.decode(response);
    localOriginDestination = await data["data"].cast<OriginDestination>();
    print(localOriginDestination);
    if(localOriginDestination!=null) {
      await _localStorageService.getBox().clear();
      await _localStorageService.getBox().addAll(localOriginDestination!.toList());
      originDestinations = _localStorageService.getOriginDestinations();
    }
  }

CodePudding user response:

I have never used Hive before but this line of code seems suspicious to me:

localOriginDestination = await data["data"].cast<OriginDestination>();

I think you want to do something along the lines of:

localOriginDestination = [
  for (final element in await data['data']) OriginDestination.fromJson(element),
];

But I can't be entirely certain without knowing what the value of await data['data'] is.


Edit, adding some more information.

The .cast method on List is only meant to be used with a type that is a subtype of the original list type, like in this example:

void main() {
  List<num> nums = [1, 2, 3];
  List<int> ints = nums.cast<int>();
  ints.add(4);
  print(ints);
}

What you are doing is essentially the same thing as this.

void main() {
  List<Map<String, int>> items = [
    {'A': 1, 'B': 2},
    {'A': 3, 'B': 4},
  ];
  final result = items.cast<ABC>();
  print(result);
}

class ABC {
  int a;
  int b;
  ABC.fromJson(Map<String, dynamic> json)
      : a = json['A'],
        b = json['B'];
}

The problem here is that the ABC class is not a subtype of Map<String, int>. Classes are not maps in the dart programming language. You need to need to call the .fromJson constructor on each element of the items list in order to get a List<ABC>.

You can do it in a few different ways.

Using map method is one approach. (you need to be on dart 2.15 for this exact syntax)

List<ABC> result = items.map(ABC.fromJson).toList();

Looping over items with a collection for is another approach.

List<ABC> result = [for (final element in items) ABC.fromJson(element)];

Looping over items with a conventional for loop is yet another approach.

List<ABC> result = [];
for (final element in items) {
  result.add(ABC.fromJson(element));
}
  • Related