从 Dart 中的 json 文件中获取嵌套列表内容,但返回“'FormContent'的实例”

Posted

技术标签:

【中文标题】从 Dart 中的 json 文件中获取嵌套列表内容,但返回“\'FormContent\'的实例”【英文标题】:Get nested list content from json file in Dart, but returning "Instance of 'FormContent' "从 Dart 中的 json 文件中获取嵌套列表内容,但返回“'FormContent'的实例” 【发布时间】:2022-01-21 03:56:19 【问题描述】:

我有一个 JSON 格式的列表,如下所示。我需要将这些列表转换为 Flutter 中的 DropDownMenu 项。为此,

    从 JSON 文件中读取数据 将数据转换为可用的类格式(FormContent 类) 创建一个返回 FormContent 列表的 Future。 读取 FutureBuilder 中的数据 将 FormContent 列表转换为 DropDownMenu 可以接受的字符串列表

在我打印items 的第一项的最后,我得到Instance of 'FormContent' 作为这次执行的结果(我在下面的FutureBuilder 小部件中标记了它)。我期待的是 JSON 文件中的"stajTuru" 列表。

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

由于存在嵌套列表格式。我尝试执行print(items[0][0].toString()); 来获取第一项的内容。但是,我收到这样的错误

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

综上所述,我需要将这些 JSON 内容转换为单独的 List<String>。就像我在上面所期待的那样。

JSON 文件

[


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

读取JSON的方法

这是我将 JSON 数据转换为列表的方法

  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 方法

最后,这是我的 FutureBuilder 来执行数据

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

【问题讨论】:

【参考方案1】:

首先,您的FormContent 类需要以某种方式进行修改。类中的所有内容当前都是私有的,因此您无法获取类中包含的数据。您也可以通过指定列表类型List&lt;String&gt; 而不是List&lt;dynamic&gt; 来更具体,并且也不需要设置属性late。这是我建议的课程重写:

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']];

至于您的readJsonData 函数,您应该通过将类型指定为Future&lt;List&lt;FormContent&gt;&gt; 而不是Future&lt;List&lt;dynamic&gt;&gt; 来更具体。我会改写如下:

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),
  ];

关于这个问题:

在我打印项目的第一项的最后,我得到了“FormContent”的实例作为这个执行的结果(我在下面的 FutureBuilder 小部件中标记了它)。我期待的是 JSON 文件中的“stajTuru”列表。

您只是打印出您从readJsonData 获得的第一个元素,它是您的FormContent 类的一个实例。您可以通过print(items[0].stajTuruItems); 来查看打印出来的stajTuru 列表。

【讨论】:

【参考方案2】:

你搞错了,表单内容属性需要公开,

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

此调用首先调用,item[0] 不是一个列表,它是一个对象,它具有 _cinsiyetItems、_stajTuruItems 等属性。

items[0] 是表单内容的一个实例,您需要访问第一个元素,您需要访问表单内容的属性,例如

items[0]. _cinsiyetItems

在这里你会发现列表字符串包含和你需要调用的第一个字符串

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

查看link

【讨论】:

【参考方案3】:

所以你有一个列表列表,并将其变成一个包含一堆列表的类,但是你忘记实现一种访问所述列表中信息的方法。

如果你想获取列表,你可以这样做:

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

这样您就可以通过items[0].firstList 访问您想要的值 你也可以像这样创建一个列表 getter:

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

这样你就可以像这样访问值:items[0].values[0]

最后,要在打印 items 变量时打印值,您需要重写 toString 方法:

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]';
  

【讨论】:

以上是关于从 Dart 中的 json 文件中获取嵌套列表内容,但返回“'FormContent'的实例”的主要内容,如果未能解决你的问题,请参考以下文章

将 JSON 解析为 Dart 中的列表

保存从 Firestore 集合中的 JSON URL 获取的列表

从字典列表中创建嵌套的 json 对象

如何从 JSON 数据中获取列表以显示在小部件中?

如何使用键路径从嵌套的字典dart中获取值。

如何使用键路径从嵌套的字典dart中获取值。