Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Parsing and typing API response in Dart/Flutter

I am querying an API endpoint (on my Node API, which I can modify) and I expect the result to be of a certain complex type. I see no real way to share types between Node and a Flutter frontend, so I define types myself like so:

enum QuestionType {
  text,
  recording,
  goal,
}

class Question {
  final String question;
  final String? subtitle;
  // final QuestionType type;
  final int? timeInSeconds;
  final int? askGoalAfterDays;
  final bool userSubmitted;

  Question(
      {required this.question,
      // required this.type,
      this.subtitle,
      this.timeInSeconds,
      this.askGoalAfterDays,
      this.userSubmitted = false});
}

I hit an endpoint and get a list of these types. The response body is:

[{
  "id": 93,
  "createdAt": "2023-03-04T02:35:24.514Z",
  "updatedAt": "2023-03-04T02:36:36.000Z",
  "question": "...",
  "subtitle": null,
  "type": "Gratitude",
  "timeInSeconds": 20,
  "askGoalAfterDays": null,
  "userSubmitted": false
}, {
  "id": 3,
  "createdAt": "2023-03-04T02:35:24.546Z",
  "updatedAt": "2023-03-04T02:35:24.546Z",
  "question": "...",
  "subtitle": null,
  "type": "Rating",
  "timeInSeconds": null,
  "askGoalAfterDays": null,
  "userSubmitted": false
}, {
  "id": 2,
  "createdAt": "2023-03-04T02:35:24.548Z",
  "updatedAt": "2023-03-04T02:36:36.000Z",
  "question": "...",
  "subtitle": null,
  "type": "Goal",
  "timeInSeconds": 20,
  "askGoalAfterDays": 0,
  "userSubmitted": false
}]

I call the API and attempt to parse the content like so:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

static Future<List<QuestionType>> getDaytime() async {
  // ...

  var response = await http.get(url);

  var res = jsonDecode(response.body) as List<QuestionType>; <-- ERROR

  if (response.statusCode == 200) {
    return [res[0], res[1]];
  } else {
    throw AdException(response.statusCode.toString());
  }
}

However when I try to parse the response I get the following error:

Unhandled Exception: type 'List<dynamic>' is not a subtype of type 'List<QuestionType>' in type cast

A few questions:

Why am I getting this error?
Is this the best way to parse and type content received from an API? There is obviously code duplication between my frontend and backend types, which seems wasteful.

>Solution :

I dont know if this can help you but I’ll give it a try:

You should try to place a fromJson(Map<String,dynamic>) method in your Question class.

So basically your class will look something like this:

enum QuestionType {
  text,
  recording,
  goal,
}

class Question {
   final String question;
   final String? subtitle;
   // final QuestionType type;
   final int? timeInSeconds;
   final int? askGoalAfterDays;
   final bool userSubmitted;

   Question({
      required this.question,
      // required this.type,
      this.subtitle,
      this.timeInSeconds,
      this.askGoalAfterDays,
      this.userSubmitted = false
   });

   Question fromJson(Map<String,dynamic> json){
      return Question(
         question: json['question'],
         subtitle: json['subtitle'],
         .......
         
      );          
   }
}

Now instead of doing var res = jsonEncode(response.body);, you should cycle the element inside response body and put it inside a new array and return it as response like this:

static Future<List<Question>> getDaytime() async {
   // ...

   var response = await http.get(url);

   if (response.statusCode == 200) {
      List<Question> res = [];

      for(var quest in response.body){
         res.add(Question.fromJson(quest));
      }

      return res;
   } else {
      throw AdException(response.statusCode.toString());
   }
}

Hope it helps! 😀

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading