skip to Main Content

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?

3

Answers


  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;
        });
      }
    
    Login or Signup to reply.
  2. 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');
        }
      }
    }
    
    Login or Signup to reply.
  3. You can modify the ChannelListModel.fromJson method to handle a list of JSON objects instead of a single object. Here’s one way to do it:

    factory ChannelListModel.fromJson(List<dynamic> jsonList) {
        return jsonList.map((json) => ChannelListModel(
            creator: json['userRef'],
            image: json['channelImage'],
            title: json['channelTitle'],
            lastPost: json['channelLastPost'],
            lastUpdate: json['lastUpdate'])
        ).toList();
      }
    

    You can also use jsonDecode to convert the response body to a List and then use the above method to convert the list to ChannelListModel

    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.
      final jsonData = jsonDecode(response.body);
      return ChannelListModel.fromJson(jsonData);
    } else {
      // If the server did not return a 200 OK response,
      // then throw an exception.
      throw Exception('Failed to load album');
    }
    

    Also, you need to update the getChannelsFromHttp function to assign the result of httpService.getChannelList() to channels variable instead of calling the function again.

    @override
      void initState() {
        super.initState();
        getChannelsFromHttp();
      }
    
      getChannelsFromHttp() async {
        var httpService = HttpServices();
        channels = await httpService.getChannelList();
        setState(() {});
      }
    

    This should solve the problem in your code.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search