132

I am trying to get the JSON response from the server and output it to the console.

Future<String> login() async {
    var response = await http.get(
        Uri.encodeFull("https://etrans.herokuapp.com/test/2"),
        headers: {"Accept": "application/json"});

    this.setState(() {
      data = json.decode(response.body);
    });


    print(data[0].name);
    return "Success!";
  }

Unhandled Exception: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'List

What could be the reason?

harunB10
  • 4,823
  • 15
  • 63
  • 107

13 Answers13

148

Here are 2 common ways this could go wrong:

  1. If your response is a json array like

    [
        {
          key1: value1,
          key2: value2,
          key3: value3,
        },
        {
          key1: value1,
          key2: value2,
          key3: value3,
        },
    
        .....
    ] 
    

    Then, we use data[0]["name"], not data[0].name Unless we cast to an object that has the name property, we cannot use data[0].name

    We cast like this data = json.decode(response.body).cast<ObjectName>();

    ObjectName can be whatever object you want (Inbuilt or Custom). But make sure it has the name property

  2. If your response is a JSON object like

    {
        dataKey: [
          {
            key1: value1,
            key2: value2,
            key3: value3,
          } 
        ] 
    }
    

    Then json.decode will return a Map, not a List

    Map<String, dynamic> map = json.decode(response.body);
    List<dynamic> data = map["dataKey"];
    print(data[0]["name"]);
    
Emmanuel Njorodongo
  • 1,004
  • 17
  • 35
Diyen Momjang
  • 1,811
  • 1
  • 11
  • 10
  • and how we convert List to List – Rammehar Sharma Nov 23 '21 at 12:11
  • @Diyen Momjang, my array is like datakey:[{key:value}, {key:value}, {key:value}] and I'm facing the same issue, can you help me out? – AMAL MOHAN N Dec 16 '21 at 09:45
  • check api response formate. e.x => var decode= json.decoder(response.body) – AK IJ Feb 06 '22 at 10:33
  • my json result is like this : {"key":"value","array:[{"key":"value"}]"}, then how i can get response in my list..can you please help me sir.....i am trying like this...List myList = [];var response = await http.get(Uri.parse(url)); var data = jsonDecode(response.body.toString()); if (response.statusCode == 200) { for (var i in data){ myList.add(UserPostModel.fromJson(i)); } print(myList); return myList; – Taki Rajani Jan 11 '23 at 17:51
  • how to add in a array? i am trying to add in array like this for (var i in data1){ myList.add(UserPostModel.fromJson(i)); } but, its give me error "String' is not a subtype of type 'bool?". @Diyen Momjang – Taki Rajani Jan 12 '23 at 17:17
87

You can use new Map<String, dynamic>.from(snapshot.value);

dKen
  • 3,078
  • 1
  • 28
  • 37
AKASH MATHWANI
  • 997
  • 8
  • 7
19

Easiest way (one dimensional):

Map<String, dynamic> data = new Map<String, dynamic>.from(json.decode(response.body));

print(data['name']);
Don Valdivia
  • 201
  • 2
  • 4
19

You are trying to case an Instance of InternalLinkedHashMap which is not possible.

You should Serialize and deserialize it back to Map<String, dynamic>.

InternalLinkedHashMap<String, dynamic> invalidMap;

final validMap =
        json.decode(json.encode(invalidMap)) as Map<String, dynamic>;
erluxman
  • 18,155
  • 20
  • 92
  • 126
  • i got the same issue. do you mind to check it? https://stackoverflow.com/questions/67564553/unhandled-exception-type-internallinkedhashmapstring-dynamic-is-not-a-sub – Blanc Chen May 23 '21 at 07:19
7

You have to convert the runtimeType of data from _InternalLinkedHashMap to an actual List.

One way is to use the List.from.

final _data = List<dynamic>.from(
  data.map<dynamic>(
    (dynamic item) => item,
  ),
);
jogboms
  • 573
  • 4
  • 11
5

If you need work with generic fields has a workaround:

class DicData
{
  int tot;
  List<Map<String, dynamic>> fields;

  DicData({
    this.tot,
    this.fields
  });

 factory DicData.fromJson(Map<String, dynamic> parsedJson) {
    return DicData(
        tot: parsedJson['tot'],
        //The magic....
        fields : parsedJson["fields"] = (parsedJson['fields'] as List)
            ?.map((e) => e == null ? null : Map<String, dynamic>.from(e))
            ?.toList()
    );
  }

}
Lucio Pelinson
  • 430
  • 5
  • 7
4

You can get this error if you are using retrofit.dart and declare the wrong return type for your annotated methods:

@GET("/search")
Future<List<SearchResults>> getResults(); 
// wrong! search results contains a List but the actual type returned by that endpoint is SearchResults 

vs

@GET("/search")
Future<SearchResults> getResults(); 
// correct for this endpoint - SearchResults is a composite with field for the list of the actual results
David Rawson
  • 20,912
  • 7
  • 88
  • 124
2

This worked for me:

  1. Create a List Data
  2. Use Map to decode the JSON file
  3. Use the List object Data to fetch the name of the JSON files
  4. With the help of index and the list object I have printed the items dynamically from the JSON file
setState(){

    Map<String, dynamic> map = json.decode(response.body);
    Data  = map["name"];
}

// for printing
Data[index]['name1'].toString(),
Roberto Caboni
  • 7,252
  • 10
  • 25
  • 39
SWETA DEY
  • 21
  • 2
  • This worked for me..1) Create a List Data ,2) Use Map to decode the json file ,3) Use the List object Data to fetch the name of the json files.4) With the help of index and the list object i have printed the items dynamically from the json file. – SWETA DEY Jul 21 '20 at 07:35
1

If your working with Firebase Cloud,make sure that you're not trying to add multiple data with same DocumentID;

firestore.collection('user').document(UNIQUEID).setData(educandos[0].toJson()).
Deekshith Hegde
  • 1,318
  • 2
  • 15
  • 27
1

Seems like this error could pop up depending on various developer faults.
In my case, I was using an EasyLocalization key but without defining it under asset/lang/en_US.json file.

Muhammed Aydogan
  • 570
  • 1
  • 4
  • 22
0

To convert from _InternalLinkedHashMap<String, dynamic> to Map<String, double> I used

Map<String,double>.from(json['rates']) 
0

this.categories = data.map((category) => Category.fromJson(category)).toList();

  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Aug 10 '23 at 04:27
-5

I had the same error using json_annotation, json_serializable, build_runner. It occurs when calling the ClassName.fromJson() method for a class that had a class property (example: class User has a property class Address).

As a solution, I modified the generated *.g.dart files of each class, by changing Map<String, dynamic>) to Map<dynamic, dynamic>) in everywhere there is a deep conversion inside the method _$*FromJson

The only problem is that you have to change it again every time you regenerate your files.

Das_Geek
  • 2,775
  • 7
  • 20
  • 26