Flutter 从 Json 转换嵌套对象返回 null

Posted

技术标签:

【中文标题】Flutter 从 Json 转换嵌套对象返回 null【英文标题】:Flutter converting Nested Object from Json returns null 【发布时间】:2021-02-04 11:20:42 【问题描述】:

我有一个像这样稍微大一点的嵌套对象:

"name": "String",       
    "exercise": [               
                                   
                   "index": 1,                                  
                               
            ],              
    "pause": [              
        "index":2,                        
    ]           

我将练习和暂停转换为 Json 字符串并将它们保存在 SQFLite 的列中。

问题

当我读取数据时,一切正常,包括列表(未嵌套),但是当我读取嵌套对象的值时,嵌套对象的两个列表都是空的。

item.exercise[0].index.toString()

Valid Value range is empty: 0

当我只读取item.exercise.toString() 时,它会返回[]。没有!= null ? [...] : List<Exercise>() 也会抛出错误

我从数据库中获得的数据(缩短)

列表:

[name: number 1, id: 56, exercise: ["index":1,"weightGoal":[15,16,17], "index":3,"weightGoal":[15,16,17]], pause: ["index":2],"index":4]]

我用它做什么

这里我尝试遍历列表并将其转换为 PlanModel 的列表:

List<PlanModel> list =
        res.isNotEmpty ? res.map((c) => PlanModel.fromJson(c)).toList() : [];
    return list;

完整模型

PlanModel planModelFromJson(String str) => PlanModel.fromJson(json.decode(str));

String planModelToJson(PlanModel data) => json.encode(data.toJson());

class PlanModel 
  PlanModel(
    this.name,
    this.id,
    this.workoutDays,
    this.pastId,
    this.timesDone,
    this.exercise,
    this.pause,
  );

  String name;
  int id;
  List<String> workoutDays;
  int pastId;
  int timesDone;
  List<Exercise> exercise;
  List<Pause> pause;

  factory PlanModel.fromJson(Map<String, dynamic> json) => PlanModel(
    name: json["name"],
    id: json["id"],
    workoutDays: List<String>.from(jsonDecode(json["workoutDays"])),
    pastId: json["pastId"],
    timesDone: json["timesDone"],
    exercise: json["Exercise"] != null ? new List<Exercise>.from(json["Exercise"].map((x) => Exercise.fromJson(x))): List<Exercise>(),
    pause: json["Pause"] != null ? new List<Pause>.from(json["Pause"].map((x) => Pause.fromJson(x))): List<Pause>(),
  );

  Map<String, dynamic> toJson() => 
    "name": name,
    "id": id,
    "workoutDays": List<dynamic>.from(workoutDays.map((x) => x)),
    "pastId": pastId,
    "timesDone": timesDone,
    "Exercise": List<dynamic>.from(exercise.map((x) => x.toJson())),
    "Pause": List<dynamic>.from(pause.map((x) => x.toJson())),
  ;





class Exercise 
  Exercise(
    this.index,
    this.name,
    this.goal,
    this.repGoal,
    this.weightGoal,
    this.timeGoal,
    this.setGoal,
  );

  int index;
  String name;
  int goal;
  int repGoal;
  List<int> weightGoal;
  int timeGoal;
  List<String> setGoal;

  Exercise.fromJson(dynamic json) 
    // anything that is wrapped around with this [] in json is converted as list
    // anything that is wrapped around with this  is map
    index = json["index"];
    name = json["name"];
    goal = json["goal"];
    repGoal = json["repGoal"];
    weightGoal = json["weightGoal"] != null ? json["weightGoal"].cast<int>() : [];
    timeGoal = json["timeGoal"];
    setGoal = json["setGoal"] != null ? json["setGoal"].cast<String>() : [];
  

  Map<String, dynamic> toJson() => 
    "index": index,
    "name": name,
    "goal": goal,
    "repGoal": repGoal,
    "weightGoal": List<dynamic>.from(weightGoal.map((x) => x)),
    "timeGoal": timeGoal,
    "setGoal": List<dynamic>.from(setGoal.map((x) => x)),
  ;


class Pause 
  Pause(
    this.index,
    this.timeInMilSec,
  );

  int index;
  int timeInMilSec;

  factory Pause.fromJson(Map<String, dynamic> json) => Pause(
    index: json["index"],
    timeInMilSec: json["timeInMilSec"],
  );

  Map<String, dynamic> toJson() => 
    "index": index,
    "timeInMilSec": timeInMilSec,
  ;

【问题讨论】:

我不确定,但我认为 key 区分大小写。您正在使用:json["Exercise"] 和 json["Pause"] @ClaudioCastro 感谢您的评论,但这很好,我也将它们都初始化为大写,因为没有变量,而是类。 @M123 您能否将您获得的所有数据、完整版的 PlanModel 和完整版的练习提供给我们,以便我对其进行测试并从中取得成果? @manofknowledge 给你 exercise 在数据库中是小写字母,但您尝试使用带有大写 E 的练习来获取它 【参考方案1】:

先阅读这篇文章。

您需要稍微修改一下这段代码才能为您工作,但想法是这样; 还要阅读代码中的注释。

如果json字符串自带[],json.decode会将其解码为List&lt;Map&gt;

如果它带有,这个json.decode会将它解码为Map

注意:在 json.decode 上使用泛型时要小心,我建议不要这样做。

jsonString 内的数据与 fromJson 函数内的值并不真正对应。您提供的 json 字符串不是很好。所以我想你会明白如何根据自己的需要来操作它。

也是主构造函数Exercise,可用于初始数据。

import 'dart:convert';
class Exercise
  Exercise(this.index, 
            this.name, 
            this.repGoal, 
            this.weightGoal, 
            this.setGoal);
  
  String index;
  String name;
  String repGoal;
  String weightGoal;
  String setGoal;


Exercise.fromJson(dynamic json) : 
    // anything that is wrapped around with this [] in json is converted as list
    // anything that is wrapped around with this  is map
    index = json["exercise"][0]["index"].toString(),
    name = json["name"].toString(),
    repGoal = json["repGoal"].toString(),
    weightGoal = json["weightGoal"].toString(),
    setGoal = json["setGoal"].toString();
  
  


void main()
  String jsonString = 'name: number 1, id: 56, exercise: ["index":1,"weightGoal":[15,16,17], pause: ["index":2]';
  Map json = json.decode(jsonString);
  Exercise.fromJson(json);
  

【讨论】:

感谢您的回答,不胜感激。我尝试了更多并编辑了我的问题,但是我得到的练习列表是空的,这意味着,如果我尝试从练习 [0] 中获取一个值,我会收到一个错误【参考方案2】:

我发现了:)

我已经将我的 fromJson 重组为这个,尤其是 jsonDecode 很重要,因为json["exercise "] 只是一个字符串。

PlanModel.fromJson(dynamic json) 
    name = json["name"];
    if (json["exercise"] != null) 
      exercise = [];
      jsonDecode(json["exercise"]).forEach((v) 
        exercise.add(Exercise.fromJson(v));
      );
    

现在我可以访问它了

PlanModel item = snapshot.data[index];

item.exercise[0].timeGoal.toString()
    

【讨论】:

我真的为你感到高兴!抱歉我没能早点回答。 @manofknowledge 谢谢你,没问题,我刚刚给你赏金,因为你处理了这个问题,谢谢

以上是关于Flutter 从 Json 转换嵌套对象返回 null的主要内容,如果未能解决你的问题,请参考以下文章

Flutter json 和 对象之间的转换

Flutter json 和 对象之间的转换

Flutter 在 ListView 返回类型 String 中显示嵌套 json 不是类型转换中类型“Map<String, dynamic>”的子类型

如何将复杂(嵌套)对象解析为 JSON 并在 Flutter 中使用 HTTP 将其发送到服务器?

如何使用从 Flutter 中的 json 解析的嵌套映射列表中的函数创建对象

Flutter:如何映射嵌套的 json 对象