Home > Software design >  How can I populate data from json link to custom model created in Flutter
How can I populate data from json link to custom model created in Flutter

Time:07-13

I'm creating an app whose one of the sections is a quiz. I've set up Strapi V4 CMS properly running on Heroku and AWS S3.

In CMS I've created a proper collection of 5 questions, their options and answer choices.

And in Flutter Project, I've created a custom question model shown below:

class QuestionModel {
  String? question;
  Map<String, bool>? answers;
  QuestionModel(this.question, this.answers);
}

List<QuestionModel> questions = [
  QuestionModel(
    "Q1?",
    {
      "opt1": bool1,
      "opt2": bool2,
      "opt3": bool3,
      "opt4": bool4,
    },
  ),
 QuestionModel(
    "Q2?",
    {
      "opt1": bool1,
      "opt2": bool2,
      "opt3": bool3,
      "opt4": bool4,
    },
  ),
  QuestionModel(
    "Q3?",
    {
      "opt1": bool1,
      "opt2": bool2,
      "opt3": bool3,
      "opt4": bool4,
    },
  ),
  QuestionModel(
    "Q4?",
    {
      "opt1": bool1,
      "opt2": bool2,
      "opt3": bool3,
      "opt4": bool4,
    },
  ),
 QuestionModel(
    "Q5?",
    {
      "opt1": bool1,
      "opt2": bool2,
      "opt3": bool3,
      "opt4": bool4,
    },
  ),
];

And in my main file I've directly called List 'questions' and placed all the conditions accordingly.

Now, these are the hard-coded values. I want to fetch them dynamically from Strapi & populate them in List 'questions', without making any changes in main.dart file.

This is what I expect:

class QuestionModel {
  String? question;
  Map<String, bool>? answers;
  QuestionModel(this.question, this.answers);
}

Future 'get function()' {
 var data = api call;
}

List<QuestionModel> questions = [
  QuestionModel(
    "data[1].Q1?",
    {
      "data[1].opt1": data[1].bool1,
      "data[1].opt2": data[1].bool2,
      "data[1].opt3": data[1].bool3,
      "data[1].opt4": data[1].bool4,
    },
  ),
 QuestionModel(
    "data[2].Q2?",
    {
      "data[2].opt1": data[2].bool1,
      "data[2].opt2": data[2].bool2,
      "data[2].opt3": data[2].bool3,
      "data[2].opt4": data[2].bool4,
    },
  ),
  QuestionModel(
    "data[3].Q3?",
    {
      "data[3].opt1": data[3].bool1,
      "data[3].opt2": data[3].bool2,
      "data[3].opt3": data[3].bool3,
      "data[3].opt4": data[3].bool4,
    },
  ),
  QuestionModel(
    "data[4].Q4?",
    {
      "data[4].opt1": data[4].bool1,
      "data[4].opt2": data[4].bool2,
      "data[4].opt3": data[4].bool3,
      "data[4].opt4": data[4].bool4,
    },
  ),
 QuestionModel(
    "data[5].Q5?",
    {
      "data[5].opt1": data[5].bool1,
      "data[5].opt2": data[5].bool2,
      "data[5].opt3": data[5].bool3,
      "data[5].opt4": data[5].bool4,
    },
  ),
];

CodePudding user response:

You can use a factory method to achieve this.

class QuestionModel {
  String? question;
  Map<String, bool>? answers;
  QuestionModel(this.question, this.answers);
  factory QuestionModel.fromJson(Map<String, dynamic> json) {
    return QuestionModel(
      question: json['question'],
      answers: json['answers']);
}
}

and call it like

QuestionModel.fromJson(json);

CodePudding user response:

Having the API return the following JSON instead to make it easier to iterate over the items:

[
  {
    "question": "Q1?",
    "options": [
      {"option": "opt1", "value": false},
      {"option": "opt2", "value": false},
      {"option": "opt3", "value": false},
    ],
  },
  {
    "question": "Q2?",
    "options": [
      {"option": "opt1", "value": false},
      {"option": "opt2", "value": false},
      {"option": "opt3", "value": false},
      {"option": "opt4", "value": false},
    ],
  },
  {
    "question": "Q3?",
    "options": [
      {"option": "opt1", "value": false},
      {"option": "opt2", "value": false},
    ],
  },
]

The code to populate questions would be something like this:

QuestionsResponse responseData = await api.getQuestions();

List<Question> questionsData = responseData.questions;

List<QuestionModel> questions = [
  for (final question in questionsData)
    QuestionModel(
      question.question,
      {for (final option in question.options) option.option: option.value},
    ),
];

In this case questionsData comes from QuestionsResponse.questions. Which in turn comes from QuestionsResponse.fromJson() call.

class Question {
  final String question;
  final List<Option> options;
  Question({required this.question, required this.options});

  Question.fromJson(Map<String, dynamic> json)
      : question = json['question'],
        options =
            (json['options'] as List).map((o) => Option.fromJson(o)).toList();

  Map<String, dynamic> toJson() => {
        "question": question,
        "options": options.map((o) => o.toJson()),
      };
}

class Option {
  final String option;
  final bool value;
  Option({required this.option, required this.value});

  Option.fromJson(Map<String, dynamic> json)
      : option = json['option'],
        value = json['value'];

  Map<String, dynamic> toJson() => {
        "option": option,
        "value": value,
      };
}

class QuestionsResponse {
  final List<Question> questions;
  QuestionsResponse({required this.questions});

  QuestionsResponse.fromJson(Map<String, dynamic> json)
      : questions =
            (json['questions'] as List).map((o) => Question.fromJson(o)).toList();

  Map<String, dynamic> toJson() => {
        "questions": questions.map((o) => o.toJson()),
      };
}
  • Related