Flutter中如何构造指定格式JSON对象并发送至服务端
修复方案
现有代码核心错误
- 状态变量作用域错误:你把
newQuiz、输入框控制器、临时字段变量全部定义在build方法内,每次Widget触发重绘就会重新初始化所有变量,之前添加的题目自然会丢失。 - 实例构造逻辑错误:添加题目时调用
Quiz.fromJson(newQuestion.toJson()),传入的是单道题的JSON结构,没有questions数组字段,Quiz的fromJson方法判断json['questions']为null,不会添加任何题目,最终得到空数组。 - 冗余的取值逻辑:不需要额外定义
question/solucion1等变量通过onChanged赋值,TextEditingController本身就可以直接获取最新的输入内容,还能避免取值不同步的问题。
修正步骤
- 首先确认你的页面是
StatefulWidget,将所有状态变量移到State类的成员位置,不要放在build方法内。 - 修改添加题目的逻辑:不要每次都新建
Quiz实例,直接往已有的Quiz实例的questions数组中追加新的题目即可。 - 发送数据时直接调用
Quiz实例的toJson()方法,就能直接得到你要求的JSON结构。
修正后核心代码
// 你的State类示例 class _CreateQuizPageState extends State<CreateQuizPage> { // 输入框控制器定义为State成员 final _questionController = TextEditingController(); final _optionAController = TextEditingController(); final _optionBController = TextEditingController(); final _optionCController = TextEditingController(); final _answerController = TextEditingController(); // 全局保存正在编辑的测验实例 final Quiz _newQuiz = Quiz(questions: []); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("创建$subjectName的新测验"), backgroundColor: Colors.green[700], ), body: ChangeNotifierProvider( create: (_) => LoginFormProvider(), child: Builder(builder: (context) { final loginFormProvider = Provider.of<LoginFormProvider>(context, listen: true); return Container( color: Colors.grey[100], padding: const EdgeInsets.symmetric(horizontal: 20), child: Center( child: ConstrainedBox( constraints: const BoxConstraints(maxHeight: 450), child: Form( key: loginFormProvider.formKey, child: Column( children: [ TextFormField( controller: _questionController, decoration: buildInputDecoration( hint: '题目内容', label: '题目', icon: Icons.edit ), ), const SizedBox(height: 10,), TextFormField( controller: _optionAController, decoration: buildInputDecoration( hint: '选项A', label: '选项A', icon: Icons.edit ), ), const SizedBox(height: 10,), TextFormField( controller: _optionBController, decoration: buildInputDecoration( hint: '选项B', label: '选项B', icon: Icons.edit ), ), const SizedBox(height: 10,), TextFormField( controller: _optionCController, decoration: buildInputDecoration( hint: '选项C', label: '选项C', icon: Icons.edit ), ), const SizedBox(height: 10,), TextFormField( controller: _answerController, cursorColor: Colors.green, decoration: buildInputDecoration( hint: '正确答案', label: '答案', icon: Icons.edit ), ), const SizedBox(height: 15,), Row( children: [ CustomOutlinedButton( onPressed: () async { // _newQuiz.toJson() 就是符合要求的JSON结构,直接传入请求即可 await createQuiz(_newQuiz.toJson(), teacherid, subjectid); }, text: "创建测验" ), const SizedBox(width: 20,), CustomOutlinedButton( onPressed: () { // 构造单道题目实例 final newQuestion = Questions( answer: _answerController.text, question: _questionController.text, solucion1: _optionAController.text, solucion2: _optionBController.text, solucion3: _optionCController.text ); // 追加到已有测验的题目列表中 _newQuiz.questions.add(newQuestion); // 清空输入框准备下一题录入 _questionController.clear(); _optionAController.clear(); _optionBController.clear(); _optionCController.clear(); _answerController.clear(); }, text: '添加题目' ), ] ) ], ), ), ), ), ); }) ), ); } // 销毁时释放控制器资源 @override void dispose() { _questionController.dispose(); _optionAController.dispose(); _optionBController.dispose(); _optionCController.dispose(); _answerController.dispose(); super.dispose(); } }
内容的提问来源于stack exchange,提问作者Irwin
相关产品推荐
相关产品推荐

