Home > Software engineering >  Get nested list content from json file in Dart, but returning "Instance of 'FormContent�
Get nested list content from json file in Dart, but returning "Instance of 'FormContent�

Time:12-19

I have a list of lists in JSON format like the following. I need to convert these lists into DropDownMenu items in Flutter. To do that,

  1. Read the data from the JSON file
  2. Convert the data to an available class format(FormContent class)
  3. Create a Future that returns a list of FormContent.
  4. Read the data inside the FutureBuilder
  5. Convert the list of FormContent into a List of Strings that DropDownMenu could accept

At the end where I print the first item of the items, I get Instance of 'FormContent' as a result of this execution(I marked it in the FutureBuilder widget, below). What I was expecting is the list of "stajTuru" in the JSON file.

["Ortopedi", "Kardiyoloji","Dermatoloji", "Pediatri"]

Since there is a nested list format. I tried to execute print(items[0][0].toString()); to get the first item's content. However, I get an error like this

Class 'FormContent' has no instance method '[]'.Receiver: Instance of 'FormContent' Tried calling: [](0)

To sum up, I need to convert these JSON contents to an individual List<String>. Like what I was expecting above.

JSON File

[


  {
    "stajTuru": [  "Ortopedi", "Kardiyoloji","Dermatoloji", "Pediatri"],
    "cinsiyet": ["Erkek","Kadın", "Diğer"],
    "etkilesimTuru": [  "Gözlem", "Yardımla yapma","Yardımsız yapma","Sanal olgu"],
    "kapsam": [  "Öykü", "Fizik Bakı", "Tanısal akıl Yürütme", "Teropötik akıl yürütme"],
    "ortam": ["Poliklinik","Servis","Acil","Ameliyathane","Dış Kurum"],
    "doktor": [  "Esra Demir","Mehmet Uçar","Kemal Yurdakul","Fehmi Öztürk","Mehmet Öz"]
  }

]

FormContent class

This is my class where I keep each of those lists

class FormContent{

  late List<dynamic> _cinsiyetItems;
  late List<dynamic> _stajTuruItems;
  late List<dynamic> _etkilesimTuruItems;
  late List<dynamic> _kapsamItems;
  late List<dynamic> _ortamItems;
  late List<dynamic> _doktorItems;

    FormContent.fromJson(Map<String,dynamic> jsonFile){
    _cinsiyetItems=jsonFile['cinsiyet']!.toList();
    _stajTuruItems=jsonFile['stajTuru']!.toList();
    _etkilesimTuruItems=jsonFile['etkilesimTuru']!.toList();
    _kapsamItems=jsonFile['kapsam']!.toList();
    _ortamItems=jsonFile['ortam']!.toList();
    _doktorItems=jsonFile['doktor']!.toList();
  }
}

Method to read JSON

This is my method where I convert the JSON data into a list

  Future<List<dynamic>> readJsonData() async{
    final jsonData = await rootBundle.rootBundle.loadString('assets/json/formdata.json');
    print(jsonData.toString());
    final list = json.decode(jsonData) as List<dynamic>;
    print("======================================");
    print(list.toString());
    var result =list.map((e) => FormContent.fromJson(e)).toList();
    print("------------------------------------------");
    print(result.toString());
    return result;
  }

FutureBuilder method

Lastly, this is my FutureBuilder to execute the data

FutureBuilder(
           future:readJsonData() ,
           builder: (context,snapshot){
             if(snapshot.hasError){
               return Text(snapshot.error.toString());
             }else if(snapshot.hasData){

               var items =snapshot.data as List<dynamic>;
               print("--------------***********************************");
                 print(items[0].toString());  //                      <--- HERE
               return
                 ListView(
                   children: [
                     myTextFieldRow("Kayıt No: ", 10,_formData.setKayitNo),
                     myDropDownContainer(_valueStajTuru,_stajTuruItems,
                         hintTextStajTuru, onChangedStajTuru),
                     // myDropDownContainer(_valueDoktor, _doktorItems, hintTextDoktor, onChangedDoktor),
                     myTextFieldRow("Hastanın Yaşı:", 3, _formData.setYas),
                    // myDropDownContainer(_valueCinsiyet, _cinsiyetItems, hintTextCinsiyet, onChangedCinsiyet),
                     myTextFieldRow("Şikayet:", 10,_formData.setSikayet),
                     myTextFieldRow("Ayırıcı Tanı:", 50,_formData.setAyiriciTani),
                     myTextFieldRow("Kesin Tanı:", 50,_formData.setKesinTani),
                     myTextFieldRow("Tedavi Yöntemi:", 100,_formData.setTedaviYontemi),
                   //  myDropDownContainer(_valueEtkilesim, _etkilesimTuruItems, hintTextEtkilesim, onChangedEtkilesim),
                  //   myDropDownContainer(_valueKapsam, _kapsamItems, hintTextKapsam, onChangedKapsam),
                    // myDropDownContainer(_valueOrtam, _ortamItems, hintTextOrtam, onChangedOrtam),
                     const SizedBox(
                       height: 20,
                     ),
                     Row(
                       mainAxisAlignment: MainAxisAlignment.end,
                       children: [
                         SizedBox(
                           width: 150,
                           height: 50,
                           child: TextButton(
                             onPressed: () {
                               setState(() {
                                 _formAdd.addNewFormToList(_formData);
                                 _formData=FormData();

                                 Navigator.push(context, MaterialPageRoute(builder: (context)=> StudentProfile(formAdd: _formAdd)));
                               });
                             },
                             child: Text(
                               "GÖNDER",
                               style: kTextStyle.copyWith(fontSize: 20),
                             ),
                             style: ButtonStyle(
                               backgroundColor: MaterialStateProperty.all<Color>(
                                 const Color(0xff4F4DBB),
                               ),
                             ),
                           ),
                         ),
                       ],
                     ),
                   ],
                 );
             } else{
               return const Center(child:CircularProgressIndicator(),);
             }
          }
         )),

CodePudding user response:

you made a mistake, form content properties need to make public,

print(items[0][0].toString());

this call first of first, item[0] does not a list, it's an object and it has properties like _cinsiyetItems, _stajTuruItems, etc.

items[0] is an instance of form content and you need access to the first element that's you need to access the property of form content like

items[0]. _cinsiyetItems

and here you find the list string contains and for the first string you need to call like

items[0]. _cinsiyetItems[0] // Erkek

And check out the link

CodePudding user response:

So you had a list of lists, and turned that into a class that holds a bunch of lists, but you forgot to implement a way to access the information within said lists.

If you want to get the lists, you gould do something like this:

class FormContent{

  late List<dynamic> _cinsiyetItems;
  late List<dynamic> _stajTuruItems;
  late List<dynamic> _etkilesimTuruItems;
  late List<dynamic> _kapsamItems;
  late List<dynamic> _ortamItems;
  late List<dynamic> _doktorItems;

  List<dynamic> get firstList => _cinsiyetItems;
  List<dynamic> get secondList => _stajTuruItems;
  List<dynamic> get thirdList => _etkilesimTuruItems;
  List<dynamic> get fourthList => _kapsamItems;
  List<dynamic> get fifthList => _ortamItems;
  List<dynamic> get sixthList => _doktorItems;


    FormContent.fromJson(Map<String,dynamic> jsonFile){
    _cinsiyetItems=jsonFile['cinsiyet']!.toList();
    _stajTuruItems=jsonFile['stajTuru']!.toList();
    _etkilesimTuruItems=jsonFile['etkilesimTuru']!.toList();
    _kapsamItems=jsonFile['kapsam']!.toList();
    _ortamItems=jsonFile['ortam']!.toList();
    _doktorItems=jsonFile['doktor']!.toList();
  }
}

this way you can access the value that you want by doing items[0].firstList You could also make a list of lists getter like so:

class FormContent{

  late List<dynamic> _cinsiyetItems;
  late List<dynamic> _stajTuruItems;
  late List<dynamic> _etkilesimTuruItems;
  late List<dynamic> _kapsamItems;
  late List<dynamic> _ortamItems;
  late List<dynamic> _doktorItems;

  List<List<dynamic>> get values => [
    _cinsiyetItems,
    _stajTuruItems,
    _etkilesimTuruItems,
    _kapsamItems,
    _ortamItems,
    _doktorItems,
  ];


    FormContent.fromJson(Map<String,dynamic> jsonFile){
    _cinsiyetItems=jsonFile['cinsiyet']!.toList();
    _stajTuruItems=jsonFile['stajTuru']!.toList();
    _etkilesimTuruItems=jsonFile['etkilesimTuru']!.toList();
    _kapsamItems=jsonFile['kapsam']!.toList();
    _ortamItems=jsonFile['ortam']!.toList();
    _doktorItems=jsonFile['doktor']!.toList();
  }
}

this way you can access the value like this: items[0].values[0]

finally, to print the values when printing the items variable, you need to override the toString method:

class FormContent{

  late List<dynamic> _cinsiyetItems;
  late List<dynamic> _stajTuruItems;
  late List<dynamic> _etkilesimTuruItems;
  late List<dynamic> _kapsamItems;
  late List<dynamic> _ortamItems;
  late List<dynamic> _doktorItems;

  List<List<dynamic>> get values => [
    _cinsiyetItems,
    _stajTuruItems,
    _etkilesimTuruItems,
    _kapsamItems,
    _ortamItems,
    _doktorItems,
  ];


    FormContent.fromJson(Map<String,dynamic> jsonFile){
    _cinsiyetItems=jsonFile['cinsiyet']!.toList();
    _stajTuruItems=jsonFile['stajTuru']!.toList();
    _etkilesimTuruItems=jsonFile['etkilesimTuru']!.toList();
    _kapsamItems=jsonFile['kapsam']!.toList();
    _ortamItems=jsonFile['ortam']!.toList();
    _doktorItems=jsonFile['doktor']!.toList();
  }

  @override
  String toString() {
    return '[$_cinsiyetItems, $_stajTuruItems, $_etkilesimTuruItems, $_kapsamItems, $_ortamItems, $doktorItems]';
  }
}

CodePudding user response:

First of all your FormContent class needs to be reworked in some way. Everything in the class is currently private which doesn't give you any way to get at the data contained within the class. Also you could be more specific by giving the lists type List<String> rather than List<dynamic>, and there is no need to make the properties late either. This is my suggested rewrite of the class:

class FormContent {
  List<String> cinsiyetItems;
  List<String> stajTuruItems;
  List<String> etkilesimTuruItems;
  List<String> kapsamItems;
  List<String> ortamItems;
  List<String> doktorItems;

  FormContent.fromJson(Map<String, dynamic> jsonFile)
      : cinsiyetItems = [...?jsonFile['cinsiyet']],
        stajTuruItems = [...?jsonFile['stajTuru']],
        etkilesimTuruItems = [...?jsonFile['etkilesimTuru']],
        kapsamItems = [...?jsonFile['kapsam']],
        ortamItems = [...?jsonFile['ortam']],
        doktorItems = [...?jsonFile['doktor']];
}

As for your readJsonData function, you should be more specific by specifying the type as Future<List<FormContent>> rather than Future<List<dynamic>>. I would rewrite as follows:

Future<List<FormContent>> readJsonData() async {
  final jsonData = await rootBundle.rootBundle.loadString('assets/json/formdata.json');
  return [
    for (final e in json.decode(jsonData)) FormContent.fromJson(e),
  ];
}

As for this issue:

At the end where I print the first item of the items, I get Instance of 'FormContent' as a result of this execution(I marked it in the FutureBuilder widget, below). What I was expecting is the list of "stajTuru" in the JSON file.

You are simply printing out the first element you got from readJsonData which is an instance of your FormContent class. You can do print(items[0].stajTuruItems); to see the stajTuru list printed out.

  • Related