1

I'm trying to use Flutter documentation to map an array data (comes from API) to the dart object. The documentation uses a single Json object, not an array. I have the following codes:

Json data:

[
    {
        "channelId" :   1
        "channelTitle"  :   "Photos"
        "channelImage"  :   pr01.jpg
        "channelLastPost"   :   null
        "lastUpdate"    :   null
        "userRef"   :   1
    },
    {
        "channelId" :   2
        "channelTitle"  :   "Science"
        "channelImage"  :   pr02.jpg
        "channelLastPost"   :   "For test ...."
        "lastUpdate"    :   "2023-01-03"
        "userRef"   :   1
    }

]

ChannelListModel.dart:

class ChannelListModel {
  String creator;
  String? image;
  String title;
  String lastPost;
  String lastUpdate;

  ChannelListModel(
      {required this.creator,
      required this.image,
      required this.title,
      required this.lastPost,
      required this.lastUpdate});

  factory ChannelListModel.fromJson(Map<String, dynamic> json) {
    return ChannelListModel(
        creator: json['userRef'],
        image: json['channelImage'],
        title: json['channelTitle'],
        lastPost: json['channelLastPost'],
        lastUpdate: json['lastUpdate']);
  }
  Map<String, dynamic> toJson() {
    return {
      "userRef" : creator,
      "channelImage" : image,
      "channelTitle" : title,
      "channelLastPost" : lastPost,
      "lastUpdate" : lastUpdate
    };
  }
}

HttpRequest.dart:

class HttpServices {
  Future<List<ChannelListModel>> getChannelList() async {
    var url = base.BaseURL.channelListUrl;
    final response = await http.get(Uri.parse(url));
    if (response.statusCode == 200) {
      // If the server did return a 200 OK response,
      // then parse the JSON.
      return List<ChannelListModel>.fromJson(jsonDecode(response.body)); //I have problem in this line
    } else {
      // If the server did not return a 200 OK response,
      // then throw an exception.
      throw Exception('Failed to load album');
    }
  }
}

ChannelPage.dart:

class _ChannelsState extends State<Channels> {

  List<ChannelListModel> channels = [];

  @override
  void initState() {
    super.initState();
    channels  = getChannelsFromHttp(); // A valid array object needs to be provided here.
  }

  getChannelsFromHttp()async{
    var httpService = HttpServices();
    var result = await httpService.getChannelList();
    return result;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView.builder(
        itemCount: channels.length,
        itemBuilder: (context, index) =>
            ChannelCard(channelModel: channels[index]),
      ),
    );
  }
}

I want to classify my codes so I decided to provided different dart files for each part. How can I fix my code?

1
  • 1
    Reminds me a bit of swift when you try to do that: List<hannelListModel>.fromJson(jsonDecode(response.body)); where elements conform to Codable, so that they can automatically get decoded. Anyway the code in ChannelList is correct (yet it should be renamed Channel). you should cast the result of jsonDecode(response.body) as a List<Map<String, dynamic>> data. below that, you make a for loop, for ( Map<String, dynamic> chunk in data) and there you can decode each chunk individually with this ChannelListModel.fromJson method of yours Commented Jan 13, 2023 at 8:08

2 Answers 2

1

Instead of

returnList<ChannelListModel>.fromJson(jsonDecode(response.body));

Try this code,

List<ChannelListModel> channels = [];
final res = jsonDecode(response.body);
channels.addAll(List<ChannelListModel>.from(
  (res).map((x) => ChannelListModel.fromJson(x))));
return channels;

Added based on comments


@override
  void initState() {
    super.initState();
    getChannelsFromHttp();
  }

  getChannelsFromHttp()async{
    var httpService = HttpServices();
    var result = await httpService.getChannelList();
    setState((){
     channels = result;
    });
  }
Sign up to request clarification or add additional context in comments.

2 Comments

I tested your solution. In ChannelPage.dart, When I use channels = getChannelsFromHttp() the emulator screen gets red and says: The Future<dynamic> is not a subtype of List<ChannelListModel> . How can I fix it?
Added that to the answer.
0

Your fromJson factory returns single ChannelListModel. You can't use List<ChannelListModel>.fromJson. Instead iterate through List and convert each json to ChannelListModel

class HttpServices {
  Future<List<ChannelListModel>> getChannelList() async {
    var url = base.BaseURL.channelListUrl;
    final response = await http.get(Uri.parse(url));
    if (response.statusCode == 200) {
      // If the server did return a 200 OK response,
      // then parse the JSON.
      //return List<ChannelListModel>.fromJson(jsonDecode(response.body));
      final data = jsonDecode(response.body) as List<dynamic>;
      return data.map((e) => ChannelListModel.fromJson(e as Map<String, dynamic>))
        .toList();

    } else {
      // If the server did not return a 200 OK response,
      // then throw an exception.
      throw Exception('Failed to load album');
    }
  }
}

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.