3

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 error

Data 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,
  };
}
8
  • Im not sure, but I think key are case sensitive. You are using: json["Exercise"] and json["Pause"] Commented Oct 21, 2020 at 14:10
  • @ClaudioCastro thanks for your comment, but this is fine, I also initialized both of them uppercase, since there are no variables, rather classses. Commented Oct 22, 2020 at 9:43
  • @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? Commented Oct 24, 2020 at 19:06
  • @manofknowledge here you go Commented Oct 24, 2020 at 20:34
  • exercise is lowercase in the database but you try to get it using Exercise with an uppercase E Commented Oct 24, 2020 at 20:48

2 Answers 2

2
+100

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);
  
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks 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
2

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()
    

3 Comments

I am really happy for you! sorry I was not able to answer sooner.
@manofknowledge Thank you, and no problem, I just gave you the bounty bc since you dealt with the problem, thanks for that
It's disappointing that the auto generated code by dart's own serialization helper is flawed. Now, I have to do this for most of my models

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.