Creating a list from JSON in Flutter

33,312

Solution 1

The reason that print(json.decode(response.body).runtimeType) prints _InternalLinkedHashMap is because the top level of your json is indeed a map; {"results":[ opens with a brace.

So, json.decode(response.body) isn't a list and cannot be cast to one. On the other hand, json.decode(response.body)['results'] is a list.

You need:

  list = json.decode(response.body)['results']
      .map((data) => Model.fromJson(data))
      .toList();

Solution 2

i tried like this and this worked

List<UserModel> users = (json.decode(response.body) as List)
      .map((data) => UserModel.fromJson(data))
      .toList();

My Json response is like :-

[{"id":4,"name":"1","email":"admin","password":"dc4b79a9200aa4630fee652bb5d7f232c503b77fb3b66df99b21ec3ff105f623","user_type":"1","created_on":"2020-01-13 12:50:28","updated_on":"2020-01-14 11:42:05","flags":"00000"},{"id":31,"name":"avi","email":"[email protected]","password":"dc4b79a9200aa4630fee652bb5d7f232c503b77fb3b66df99b21ec3ff105f623","user_type":"1","created_on":"2020-03-15 11:39:16","updated_on":"2020-03-15 11:39:16","flags":null}]

Solution 3

The following was working for me:

List<Model>.from(
  json.decode(response.body)
  .map((data) => Model.fromJson(data))
)
Share:
33,312
Ciprian
Author by

Ciprian

Updated on February 16, 2022

Comments

  • Ciprian
    Ciprian over 2 years

    Following an online example I have the following code:

    _fetchData() async {
        setState(() {
          isLoading = true;
        });
    
        final response = await http.get(
            "https://apiurl...");
    
        if (response.statusCode == 200) {
          print(json.decode(response.body).runtimeType); // _InternalLinkedHashMap<String, dynamic>
    
          list = (json.decode(response.body) as List)
              .map((data) => Model.fromJson(data))
              .toList();
    
          setState(() {
            isLoading = false;
          });
        } else {
          throw Exception('Failed to load');
        }
      }
    

    Which returns this error:

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

    This is the response from the API:

    {"results":[{"docid":"123434","title":"A title"}, ...]}
    

    Model:

    class Model {
      final String title;
      final String docid;
    
      Model._({this.title, this.docid});
    
      factory Model.fromJson(Map<String, dynamic> json) {
        return new Model._(
          title: json['title'],
          docid: json['docid'],
        );
      }
    }
    

    I understand that the above factory is expecting the argument to be Map<String, dynamic> and the format of the json is different and can be changed, but want to know how to make it work with this format.

    *** Edit

    Working ListView

    body: Column(
        children: <Widget>[
          Padding(
            padding: EdgeInsets.all(10.0),
            child: TextField(
              onChanged: (value) {
                ...
              },
              controller: _searchController,
              decoration: InputDecoration(
    
              ...
              ),
            ),
          ),
          Expanded(
            child: SizedBox(
              height: 200.0,
              child: ListView.builder(
                  itemCount: list.length,
                  itemBuilder: (BuildContext context, int index) {
                    return Text(list[index].title);
                  }),
            ),
          )
        ],
      ),
    
  • Ciprian
    Ciprian about 5 years
    Hey, thank you for your answer. print(list) returns [Instance of 'Model', Instance of 'Model', ...] Is this correct? I can't seem to get the ListView working. Added that to the question as well.
  • Richard Heap
    Richard Heap about 5 years
    That would need to be list[index].title. Your list is now correctly print that you have several models. Index indexes into the list, giving you one model, and you access the member variable by name with a dot.
  • Ciprian
    Ciprian about 5 years
    I'm sure I tried with dot, but I'll look again. Thanks
  • Ciprian
    Ciprian about 5 years
    I edited my question showing the how I want to use the ListView widget. Flutter is returning this message: flutter: Another exception was thrown: RenderBox was not laid out: RenderViewport#67a95 NEEDS-LAYOUT NEEDS-PAINT
  • Ciprian
    Ciprian about 5 years
    Found the answer here: stackoverflow.com/questions/52801201/…. Seems that the ListView widget needs to be wrapped by a a SizedBox
  • Richard Heap
    Richard Heap about 5 years
    great! Try Expanded too as an alternative to sized box.
  • Dekple
    Dekple over 3 years
    I created a model class but nothing is called when trying to create the list. Is there a way to do this without creating a class?
  • Dekple
    Dekple over 3 years
    I created a model class but nothing is called when trying to create the list. Is there a way to do this without creating a class?
  • Abir Ahsan
    Abir Ahsan almost 2 years
    because your json file is List directly. but here this list under a map