Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get nested list content from json file in Dart, but returning "Instance of 'FormContent' "

Tags:

json

flutter

dart

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(),);
             }
          }
         )),

like image 677
Demir Avatar asked Dec 18 '21 19:12

Demir


People also ask

Can JSON have nested list?

A resource representation, in the JSON format, is a complex JSON object. Lists of items and nested data structures are represented as JSON arrays and nested JSON objects.


2 Answers

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.

like image 158
mmcdon20 Avatar answered Oct 20 '22 11:10

mmcdon20


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

like image 23
Jahidul Islam Avatar answered Oct 20 '22 11:10

Jahidul Islam