Error Occured: type 'Null' is not a subtype of type 'List<dynamic>' in type cast

Viewed 86

I try to display json as image. But instead image, it triggers error. I have tried to change the code but it didn't work.

class _MainPage extends State<MainPage> {
  Future<List<Data>> _fetchData() async {
    final jsondata =
        await rootBundle.rootBundle.loadString('assets/datakomik.json');
    final list = json.decode(jsondata)["data"] as List<dynamic>;

    return list.map((e) => Data.fromJson(e)).toList();
  }

  Future<List<KomikModel>> _listKomik() async {
    final jsongambar =
        await rootBundle.rootBundle.loadString('assets/datakomik.json');
    final list = json.decode(jsongambar)["image"] as List<dynamic>;  <-- Error is in this line

    return list.map((e) => KomikModel.fromJson(e)).toList();
  }

Here is datakomik.json where I set the json. The data that I want to display is "judul" and "image" that contains title and picture of the comic. I only know that I can only set one data after (jsongambar), so I only set ["image"] after it. But it triggers an error like I've said.

{
  "data": [
    {
      "kategori": "Update terbaru",
      "data": [
        {
          "judul": "Jujutsu Kaisen",
          "image": "images/Jujutsu Kaisen_Volume 1.webp"
        },
        {
          "judul": "Vinland Saga",
          "image": "images/Vinland Saga_volume 01.jpg"
        },
        {
          "judul": "Hunter x Hunter",
          "image": "images/HxH_Volume 10.jpg"
        },
        {
          "judul": "One Piece",
          "image": "images/One Piece_Volume 1.webp"
        }
      ]
    },
    {
      "kategori": "Action",
      "data": [
        {
          "judul": "Bleach",
          "image": "images/Bleach-volume-73.jpg"
        },
        {
          "judul": "Naruto",
          "image": "images/naruto_volume 63.jpg"
        },
        {
          "judul": "Dragon Ball Super",
          "image": "images/dragon-ball-super_volume 14.webp"
        },
        {
          "judul": "Hunter x Hunter",
          "image": "images/HxH_Volume 10.jpg"
        },
        {
          "judul": "One Punch Man",
          "image": "images/one punch man_volume 25.jpg"
        },
        {
          "judul": "My Hero Academia",
          "image": "images/My Hero Academia_volume 4.jpg"
        }
      ]
    },
    {
      "kategori": "Baru dibaca",
      "data": [
        {
          "judul": "Kaguya-sama: Love is War",
          "image": "images/kaguya-sama_Volume 22.jpg"
        }
      ]
    }
  ]
}

This is where I call _listKomik()

FutureBuilder<List<KomikModel>>(
                  future: _listKomik(),
                  builder: (context, snapshot) {
                    if (!snapshot.hasData) {
                      return const Center(
                        child: CircularProgressIndicator(),
                      );
                    }
2 Answers

This method will give you a list of image URLs from JSON.

Future<List<Map<String,String>>> _listKomik() async {
final jsongambar =
await rootBundle.rootBundle.loadString('assets/datakomik.json');
final list = jsongambar["data"] as List<dynamic>;
List<Map<String,String>> imageList = [];
list.forEach((element) {
  final data = element["data"] as List<dynamic>;
  for (var value in data) {
    imageList.add({"image":value["image"],"name":value["image"]});
  }
});

return imageList;}

also change this code as well

FutureBuilder<List<Map<String,String>>(
              future: _listKomik(),
              builder: (context, snapshot) {
                if (!snapshot.hasData) {
                  return const Center(
                    child: CircularProgressIndicator(),
                  );
                }
return Column(
                  children: <Widget>[
                    Container(
                      padding: const EdgeInsets.all(8),
                      height: 270,
                      child: ListView(
                        scrollDirection: Axis.horizontal,
                        children: snapshot.data!
                            .map((_data) => Column(
                                  children: <Widget>[
                                    Card(
                                      child: Text(_data["image"].toString()), <-- image getter
                                    ),
                                  ],
                                ))
                            .toList(),
                      ),
                    ),
                  ],
                );

and if you want show image then you can use snapshot.data["image"] or snapshot.data["name"]

I am not sure of the structure of KomikModel so i've made a best guess

Future<List<KomikModel>> _listKomik() async {
  final jsongambar =
        await rootBundle.rootBundle.loadString('assets/datakomik.json');
    
  final list = json.decode(jsongambar) as Map<String, dynamic>;

  final komiks = list['data'] as List<dynamic>;

  return komiks
        .map((e) => KomikModel.fromMap(e as Map<String, dynamic>))
        .toList();
}

class KomikModel {
  final String kategori;
  final List<Manga> data;

  KomikModel({
    required this.kategori,
    required this.data,
  });

  Map<String, dynamic> toMap() {
    return {
      'kategori': kategori,
      'data': data.map((x) => x.toMap()).toList(),
    };
  }

  factory KomikModel.fromMap(Map<String, dynamic> map) {
    return KomikModel(
      kategori: map['kategori'],
      data: List<Manga>.from(map['data']?.map((x) => Manga.fromMap(x))),
    );
  }

  String toJson() => json.encode(toMap());

  factory KomikModel.fromJson(String source) =>
      KomikModel.fromMap(json.decode(source));
}

class Manga {
  final String judul;
  final String image;

  Manga({
    required this.judul,
    required this.image,
  });

  Map<String, dynamic> toMap() {
    return {
      'judul': judul,
      'image': image,
    };
  }

  factory Manga.fromMap(Map<String, dynamic> map) {
    return Manga(
      judul: map['judul'],
      image: map['image'],
    );
  }

  String toJson() => json.encode(toMap());

  factory Manga.fromJson(String source) => Manga.fromMap(json.decode(source));
}

You can access image as normal through KomikModel

final List<KomikModel> komiks = await _listKomiks();
print(komiks[0].data[0].image);

// or a list of all images in a komik
final List<String> images = komiks[0].data.fold<List<String>>(
      [], (prev, manga) => [...prev, manga.image])

or display all the images in Flutter as such

class KomikList extends StatefulWidget {
  const KomikList({super.key});

  @override
  State<KomikList> createState() => _KomikListState();
}

class _KomikListState extends State<KomikList> {
  Future<List<KomikModel>> _listKomik() async {
    final jsongambar = await rootBundle.loadString('assets/datakomik.json');
    final data = json.decode(jsongambar) as Map<String, dynamic>;

    final list = data['data'] as List<dynamic>;

    return list
        .map((e) => KomikModel.fromMap(e as Map<String, dynamic>))
        .toList();
  }

  List<Manga> _mangaList(List<KomikModel> komiks) {
    return komiks.fold<List<Manga>>([], (prev, el) {
      return [...prev, ...el.data];
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Komiks'),
      ),
      body: FutureBuilder<List<KomikModel>>(
        future: _listKomik(),
        builder: (context, snapshot) {
          if (!snapshot.hasData) {
            return const Center(
              child: CircularProgressIndicator(),
            );
          }

          final mangaList = _mangaList(snapshot.data!);

          return ListView.builder(
            padding: const EdgeInsets.all(16.0),
            itemCount: mangaList.length,
            itemBuilder: (context, index) {
              final manga = mangaList[index];
              return Column(
                children: [
                  Card(
                    clipBehavior: Clip.antiAlias,
                    child: Image.asset(
                      'assets/${manga.image}',
                      height: 300,
                    ),
                  ),
                  Text(manga.judul)
                ],
              );
            },
          );
        },
      ),
    );
  }
}
Related