Flutter converting Nested Object from Json returns null
Solution 1
I found it out :)
I have restructured my fromJson to this, especially the jsonDecode was important, because json["exercise "]
was only a String.
PlanModel.fromJson(dynamic json) {
name = json["name"];
if (json["exercise"] != null) {
exercise = [];
jsonDecode(json["exercise"]).forEach((v) {
exercise.add(Exercise.fromJson(v));
});
}}
now I can access it with
PlanModel item = snapshot.data[index];
item.exercise[0].timeGoal.toString()
Solution 2
Read this first.
You need to tweek this code a little to work for you but the idea is that; also read comment in the code.
if json string comes with []
those around, json.decode will decode it as List<Map>
.
if it comes with {}
this json.decode will decode it as Map
.
note: be careful while using generics on json.decode I reccommend not to.
data inside the jsonString
does not really corresponds with the values inside the fromJson
function. json string which you have provided was not really good. so I think you will understand how to manipulate it for your needs.
also main constructor Exercise
you can use for initial data.
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);
}
m123
Updated on December 07, 2022Comments
-
m123 over 1 year
I have a Nested Object like this just a bit bigger:
"name": "String", "exercise": [ { "index": 1, } ], "pause": [ {"index":2}, ]
I convert the exercise and pause to a Json String and save them in a column in SQFLite.
The problem
When I read the Data everything works fine including the List (not nested) but both list's of nested Object are empty when I read a value of the nested object it gives an error.
item.exercise[0].index.toString() Valid Value range is empty: 0
When I read only
item.exercise.toString()
it returns[]
. Without!= null ? [...] : List<Exercise>()
it also throws an errorData I get from my Database (shortened)
List of:
[{name: number 1, id: 56, exercise: [{"index":1,"weightGoal":[15,16,17]}, {"index":3,"weightGoal":[15,16,17]}], pause: [{"index":2}]},{"index":4}]}]
What I do with it
Here I try to go through the list and convert it into a List of PlanModel:
List<PlanModel> list = res.isNotEmpty ? res.map((c) => PlanModel.fromJson(c)).toList() : []; return list;
Full model
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, }; }
-
Claudio Castro over 3 yearsIm not sure, but I think key are case sensitive. You are using: json["Exercise"] and json["Pause"]
-
m123 over 3 years@ClaudioCastro thanks for your comment, but this is fine, I also initialized both of them uppercase, since there are no variables, rather classses.
-
man of knowledge over 3 years@M123 can you please give us all the data you get, full version of the PlanModel, and full version of your Exercise so I can test it and make something work from it?
-
m123 over 3 years@manofknowledge here you go
-
Pieter van Loon over 3 yearsexercise is lowercase in the database but you try to get it using Exercise with an uppercase E
-
man of knowledge over 3 yearsI'll get back to you tomorrow it's late here
-
Pieter van Loon over 3 yearsI mean change it in the fromJson from Exercise to exercise
-
m123 over 3 years@PietervanLoon I already understood what you mean, it may be that this is part of the problem. But if I switch to lower case letters then is: if (snapshot.hasData) {} in "where I read it" false, that means no more data arrives. Thanks anyway
-
-
m123 over 3 yearsThanks for your answer, appreciate it. I tried a bit more around and edited my Question, but the List of exercise I get is empty, that means, if I try to get a value from exercise [0], I get an error
-
man of knowledge over 3 yearsI am really happy for you! sorry I was not able to answer sooner.
-
m123 over 3 years@manofknowledge Thank you, and no problem, I just gave you the bounty bc since you dealt with the problem, thanks for that