Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

type '_InternalLinkedHashMap<dynamic, dynamic>' is not a subtype of type 'Map<String, dynamic>' in type cast #351

Closed
HerrNiklasRaab opened this issue Oct 20, 2018 · 28 comments

Comments

@HerrNiklasRaab
Copy link

I get following error, when i want to deserialize an object with a property of type List<> containing another serializeable object. If i change "ChatMember.fromJson(e as Map<String, dynamic>)" to "Map<String, dynamic>.from(e)" everything works perfect. Can you fix this, is there any workaround possible so i can continue my work?

E/flutter (21470): [ERROR:flutter/shell/common/shell.cc(181)] Dart Error: Unhandled exception:
E/flutter (21470): type '_InternalLinkedHashMap<dynamic, dynamic>' is not a subtype of type 'Map<String, dynamic>' in type cast
E/flutter (21470): #0      Object._as (dart:core/runtime/libobject_patch.dart:78:25)
E/flutter (21470): #1      _$ChatFromJson.<anonymous closure> (file:///C:/Flutter/src/hapi/lib/datamodels/chat.g.dart:13:56)
E/flutter (21470): #2      MappedListIterable.elementAt (dart:_internal/iterable.dart:414:29)
E/flutter (21470): #3      ListIterable.toList (dart:_internal/iterable.dart:219:19)
E/flutter (21470): #4      _$ChatFromJson (file:///C:/Flutter/src/hapi/lib/datamodels/chat.g.dart:14:13)
E/flutter (21470): #5      new Chat.fromJson (package:hapi/datamodels/chat.dart:22:55)
E/flutter (21470): #6      ChatsModel.getChats.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:hapi/models/chats_model.dart:24:72)
E/flutter (21470): #7      FirestoreHelper.fromListToMap.<anonymous closure> (package:hapi/framework/helper/firestorehelper.dart:8:36)
E/flutter (21470): #8      MapBase._fillMapWithMappedIterable (dart:collection/maps.dart:67:32)
E/flutter (21470): #9      new LinkedHashMap.fromIterable (dart:collection/linked_hash_map.dart:124:13)
E/flutter (21470): #10     FirestoreHelper.fromListToMap (package:hapi/framework/helper/firestorehelper.dart:6:16)
E/flutter (21470): #11     ChatsModel.getChats.<anonymous closure>.<anonymous closure> (package:hapi/models/chats_model.dart:24:31)
E/flutter (21470): #12     _RootZone.runUnaryGuarded (dart:async/zone.dart:1314:10)
E/flutter (21470): #13     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:336:11)
E/flutter (21470): #14     _DelayedData.perform (dart:async/stream_impl.dart:591:14)
E/flutter (21470): #15     _StreamImplEvents.handleNext (dart:async/stream_impl.dart:707:11)
E/flutter (21470): #16     _PendingEvents.schedule.<anonymous closure> (dart:async/stream_impl.dart:667:7)
E/flutter (21470): #17     _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
E/flutter (21470): #18     _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)
// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'chat.dart';

// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************

Chat _$ChatFromJson(Map<String, dynamic> json) {
  return Chat(
      members: (json['members'] as List)
          ?.map((e) =>
              e == null ? null : ChatMember.fromJson(e as Map<String, dynamic>))
          ?.toList(),
      memberIds: (json['memberIds'] as List)?.map((e) => e as String)?.toList())
    ..creation = json['creation'] == null
        ? null
        : DateTime.parse(json['creation'] as String)
    ..lastUpdate = json['lastUpdate'] == null
        ? null
        : DateTime.parse(json['lastUpdate'] as String);
}

Map<String, dynamic> _$ChatToJson(Chat instance) => <String, dynamic>{
      'creation': instance.creation?.toIso8601String(),
      'lastUpdate': instance.lastUpdate?.toIso8601String(),
      'members': instance.members,
      'memberIds': instance.memberIds
    };
@HerrNiklasRaab
Copy link
Author

Workaround:

  factory Chat.fromJson(Map<String, dynamic> json) {
    json["members"] = (json['members'] as List)
          ?.map((e) =>
              e == null ? null : Map<String, dynamic>.from(e))
          ?.toList();
     return _$ChatFromJson(json);  
  }

@kevmoo
Copy link
Collaborator

kevmoo commented Oct 20, 2018

Duplicate of flutter/flutter#17417 – I'll try to take a look today...

@kevmoo kevmoo closed this as completed Oct 20, 2018
@kevmoo
Copy link
Collaborator

kevmoo commented Oct 20, 2018

Actually, it looks like the map is coming from package:hapi – not sure what that is.

You can configure your generator to use anyMap – see https://pub.dartlang.org/packages/json_serializable under Build Configuration – set any_map: true and you should be good!

Or change your map generation to create Map<String, dynamic> instead of Map<dynamic, dynamic>

@HerrNiklasRaab
Copy link
Author

Tried any_map: true. But this didn't changed anything. Only working with the provided workaround.

@kevmoo
Copy link
Collaborator

kevmoo commented Oct 20, 2018

Glad you figured it out!

@HerrNiklasRaab
Copy link
Author

@kevmoo Sorry, for the unclear answer. Setting any_map: true didn't change anything, this did not solved my problem.

@kevmoo
Copy link
Collaborator

kevmoo commented Oct 21, 2018

If the generated code didn't change at all, then you likely have something wrong with your configuration.

@ajplumlee33
Copy link

I couldn't get any_map to work either. However, I tried nullable: false and that fixed the problem for me

@pujitm
Copy link

pujitm commented Dec 25, 2018

neither nullable: false nor anyMap: true worked for me, but the original workaround did.

In my case, I had a Map of another serializable object. My workaround in the fromJson method was as follows:

json["owner"] = Map<String, dynamic>.from(json["owner"]);

@lukepighetti
Copy link

lukepighetti commented Feb 22, 2019

Running into this now. It's immediately apparent when trying to serialize JSON from firebase_database for some reason.

@lukepighetti
Copy link

type '_InternalLinkedHashMap<dynamic, dynamic>' is not a subtype of type 'Map<String, dynamic>' in type cast

None of these works.

Print statement shows a map coming through.

      contentRef(schemaKey)
          .child(entryId)
          .once()
          .then((snap) => Entry.fromJson(snap.value.cast<String, dynamic>()));
      contentRef(schemaKey)
          .child(entryId)
          .once()
          .then((snap) => Entry.fromJson(Map.from(snap.value)));
      contentRef(schemaKey).child(entryId).once().then(
          (snap) => Entry.fromJson(Map<String, dynamic>.from(snap.value)));

using

  firebase_database: ^2.0.1+1
  json_serializable: ^2.0.2

@kevmoo
Copy link
Collaborator

kevmoo commented Feb 24, 2019

See flutter/flutter#17417 – please add a 👍 there to encourage the flutter folks to run on it

@lukepighetti
Copy link

lukepighetti commented Feb 25, 2019

Thanks @kevmoo , I was able to move forward by using any_map: true and switching to MyClass.fromJson(Map json) instead of MyClass.fromJson(Map<String, dynamic> json)

@agueroveraalvaro
Copy link

agueroveraalvaro commented Jun 14, 2019

Only this was my solution

    Map data = jsonDecode(result.body);
    List<dynamic> list = List();
    list = data["result"].map((result) => new MyModel.fromJson(result)).toList();

    for(int b=0;b<list.length;b++)
    {
      MyModel myModel = list[b] as MyModel;
      _add(myModel);
    }
factory MyModel.fromJson(Map<String, dynamic> json) {
    return new MyModel(
      id: json['id'],
      name: json['name']
    );
  }

@rv786
Copy link

rv786 commented Jul 31, 2019

neither nullable: false nor anyMap: true worked for me, but the original workaround did.

In my case, I had a Map of another serializable object. My workaround in the fromJson method was as follows:

json["owner"] = Map<String, dynamic>.from(json["owner"]);

The best idea to Fix The Error
Unhandled Exception: type 'List<dynamic>' is not a subtype of type 'List<Map<String, dynamic>>' in type cast
From jsonDecode("[]") as List<Map<String, dynamic>> To List<Map<String, dynamic>>.from(jsonDecode("[]"))

@eeeeeson
Copy link

eeeeeson commented Aug 1, 2019

When argument data pass through by MethodChannel or EventChannel. we should use codec JSONMethodCodec which will ensure type as Map<String, dynamic> automatically.

@kevmoo
Copy link
Collaborator

kevmoo commented Aug 1, 2019 via email

@zemunkh
Copy link

zemunkh commented Aug 30, 2020

Workaround:

  factory Chat.fromJson(Map<String, dynamic> json) {
    json["members"] = (json['members'] as List)
          ?.map((e) =>
              e == null ? null : Map<String, dynamic>.from(e))
          ?.toList();
     return _$ChatFromJson(json);  
  }

Thanks, I skipped this answer almost 10 times. You saved my life. Huge appreciate. 👍

@lukepighetti
Copy link

lukepighetti commented Feb 23, 2021

This problem is still apparent and it's very annoying. If you try to unwrap any nested maps from Realtime Database it falls apart. Furthermore, the errors provided for some reason do not show stack into json_serializable, so it's very difficult to track down the source.

@kevmoo
Copy link
Collaborator

kevmoo commented Feb 23, 2021 via email

@lukepighetti
Copy link

lukepighetti commented Feb 23, 2021

Just for the sake of my understanding, is there any reason why json_serializable can't do a Map<String,dynamic>.from() when it's expecting a map? Would that resolve the issue?

I suspect I'm going to have to make a visitor to mutate nested maps into Map<String,dynamic> to coerce these realtime database response objects into something palatable for json_serializable

@lukepighetti
Copy link

lukepighetti commented Feb 23, 2021

If I edit the json_serliazble code to change e as Map<String,dynamic> to Map<String,dynamic>.from(e) it works as expected

As implemented

_$_FBList _$_$_FBListFromJson(Map<String, dynamic> json) {
  return _$_FBList(
    info: json['info'] == null
        ? null
        : FBListInfo.fromJson(json['info'] as Map<String, dynamic>),
    members: (json['members'] as Map<String, dynamic>)?.map(
      (k, e) => MapEntry(k,
          e == null ? null : FBListMember.fromJson(e as Map<String, dynamic>)),
    ),
    items: (json['items'] as Map<String, dynamic>)?.map(
      (k, e) => MapEntry(
          k, e == null ? null : FBListItem.fromJson(e as Map<String, dynamic>)),
    ),
  );
}

Change to allow toJson to work with realtime database response objects.

_$_FBList _$_$_FBListFromJson(Map<String, dynamic> json) {
  return _$_FBList(
    info: json['info'] == null
        ? null
        : FBListInfo.fromJson(json['info'] as Map<String, dynamic>),
    members: (json['members'] as Map<String, dynamic>)?.map(
      (k, e) => MapEntry(
          k,
          e == null
              ? null
              : FBListMember.fromJson(Map<String, dynamic>.from(e))),
    ),
    items: (json['items'] as Map<String, dynamic>)?.map(
      (k, e) => MapEntry(k,
          e == null ? null : FBListItem.fromJson(Map<String, dynamic>.from(e))),
    ),
  );
}

@lukepighetti
Copy link

lukepighetti commented Feb 23, 2021

I was able to get it to work with a combination of things

any_map: true

factory FBList.fromJson(Map<String, dynamic> json) => _$FBListFromJson(json);

FBList.fromJson(Map.from(listPayload))

But I am still curious to hear your thoughts about the solution in my previous comment.

@kevmoo
Copy link
Collaborator

kevmoo commented Feb 23, 2021

Yeah any_may is your best bet here.

The problem w/ your proposal is it copies data unnecessarily. I guess we could do a cast. But it drives me nuts to create these types of work-arounds for other folks code.

@lukepighetti
Copy link

I'm going to consider this resolved, thanks for the reply.

@exeptionerror
Copy link

[Solved] Unhandled Exception: InternalLinkedHashMap‘ is not a subtype of type ‘List

@JanobA99
Copy link

Actually, it looks like the map is coming from package:hapi – not sure what that is.

You can configure your generator to use anyMap – see https://pub.dartlang.org/packages/json_serializable under Build Configuration – set any_map: true and you should be good!

Or change your map generation to create Map<String, dynamic> instead of Map<dynamic, dynamic>

thanks bro

@stanley-shavy
Copy link

create UserData class then pass data without the <String, dynamic>
UserData.fromRTDB(Map data)

The data after fetching should be the same cast it to map without the <String, dynamic>
final data = snapshot.value as Map;
final userI = UserData.fromRTDB(data);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests