0
votes

I am having difficulties handling json request. While trying to process it I get the following error:

I/flutter ( 9296): Exception: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'List' in type cast

I would be grateful if you can help fix this.

main file:

import 'package:flutter/material.dart';
import 'package:practice_5/model/breedModel.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'dart:async';
import 'package:flutter/foundation.dart';

Future<List<Dog>> fetchPhotos(http.Client client) async {
  final response =
  await client.get('https://dog.ceo/api/breeds/image/random');
  return compute(parseDog, response.body);
}

List<Dog> parseDog(responseBody) {
  final parsed = jsonDecode(responseBody) as List;
  return parsed.map<Dog>((json) => Dog.fromJson(json)).toList();
}

class BreedListTile extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return FutureBuilder<List<Dog>>(
      future: fetchPhotos(http.Client()),
      builder: (context, snapshot) {
        if (snapshot.hasError) print(snapshot.error);
        return snapshot.hasData
            ? DogListTile (dogs: snapshot.data,)
            : Center (child: CircularProgressIndicator());
      },
    );
  }
}

class DogListTile extends StatelessWidget {
  final List<Dog> dogs;

  DogListTile({Key key, this.dogs}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
        itemCount: dogs.length,
        itemBuilder: (context, index) {
          return ListTile (
            title: Text ('Title'),
            subtitle: Text ('Subtitle'),
            leading: Image.network(dogs[index].message),
          );
        });
  }
}

Class model

class Dog {
  Dog({
    this.message,
    this.status,
  });

  final String message;
  final String status;

  factory Dog.fromJson(Map<String, dynamic> json) => Dog(
    message: json["message"] == null ? null : json["message"],
    status: json["status"] == null ? null : json["status"],
  );

  Map<String, dynamic> toJson() => {
    "message": message == null ? null : message,
    "status": status == null ? null : status,
  };
}
1
The first thing to check is that jsonDecode(responseBody) is returning a Map and not a List. - Abion47
tried final parsed = jsonDecode(responseBody); return parsed <Dog>((json) => Dog.fromJson(json)); get I/flutter (10684): Exception: NoSuchMethodError: Class '_InternalLinkedHashMap<String, dynamic>' has no instance method 'call'. I/flutter (10684): Receiver: _LinkedHashMap len:2 I/flutter (10684): Tried calling: call<Dog>(Closure: (dynamic) => Dog) - Sam324
You called parsed<Dog>(...). parsed is a Map object, not a method or function type. - Abion47
How do I then get the properly wrapped response? - Sam324
The response is a map. It's not clear how to convert it into the list you are expecting without seeing the actual JSON response you are dealing with. - Abion47

1 Answers

0
votes

The output from the API url in the snippet is:

{
  "message": "https://images.dog.ceo/breeds/spaniel-sussex/n02102480_8117.jpg",
  "status": "success"
}

which is not a list.

The API returns just single Dog object rather than a list of Dog objects.

You can use this to parse a single Dog object:

final parsed = jsonDecode(responseBody);
Dog dog = Dog.fromJson(parsed))