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

Time:09-08

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(),
                      );
                    }

This is where I set a getter for image

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(),
                          ),
                        ),
                      ],
                    );

CodePudding user response:

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(),
                  );
                }

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

CodePudding user response:

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 any other way you would normaly access a Future in Flutter.

  • Related