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,
- Read the data from the JSON file
- Convert the data to an available class format(FormContent class)
- Create a Future that returns a list of FormContent.
- Read the data inside the FutureBuilder
- 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.