19

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);
              }),
        ),
      )
    ],
  ),
2
  • try to use jsonDecode instead json.decode. Commented May 8, 2019 at 23:17
  • On this line json.decode(response.body) as List, instead try with json.decode(response.body) as List<String, dynamic> and let us know. Commented May 8, 2019 at 23:25

6 Answers 6

37

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();
Sign up to request clarification or add additional context in comments.

7 Comments

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.
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.
I'm sure I tried with dot, but I'll look again. Thanks
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
Found the answer here: stackoverflow.com/questions/52801201/…. Seems that the ListView widget needs to be wrapped by a a SizedBox
|
16

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}]

1 Comment

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?
6

The following was working for me:

List<Model>.from(
  json.decode(response.body)
  .map((data) => Model.fromJson(data))
)

Comments

1

For the list:

  List<ModelClass> modelList=<ModelClass>[];

  for (var json in result[HttpKeys.data]) {
    modelList.add(ModelClass.fromJson(json));
  }

The model class:

class ModelClass {
   ModelClass({
     this.id = '',
     this.title = '',
});

 String id;
 String title;

 factory ModelClass.fromJson(Map<String, dynamic> json) => ModelClass(
    id: json['_id'],
    title: json['title'],
  );

 Map<String, dynamic> toJson() => {
    '_id': id,
    'title': title,
  };
 }

Comments

0

None of the above worked for me here is my solution.

 List<dynamic> jsonResponse = json.decode(response.body);
 List<ActiveOrderData> mReturnVal = [];
 jsonResponse.map((element) {mReturnVal.add(new ActiveOrderData.fromJson(element));}).toList();

1 Comment

because your json file is List directly. but here this list under a map
-4

the following solve this code and work fine :

final response = await http.get("https://about.google/static/data/locations.json");

final data = jsonDecode(response.body)['offices'];

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.