在 Flutter 中显示 JSON 数据

Posted

技术标签:

【中文标题】在 Flutter 中显示 JSON 数据【英文标题】:Display JSON data in Flutter 【发布时间】:2021-11-27 04:38:17 【问题描述】:

我想显示一些我从 API 接收到的数据,这是我从 Node JS 服务器接收到的数据:

[
    
        "NAME": "Matematicas"
    ,
    
        "NAME": "Naturales"
    ,
    
        "NAME": "Ciencias Sociales"
    ,
    
        "NAME": "Lenguaje"
    ,
    
        "NAME": "Religion"
    
]

这就是我在前端接收数据的方式(由@Mofidul Islam 更新):

Future<List<Subject>> fetchSubject() async 
  var url = Uri.http('localhost:8000', "/subjects");
  var prefs = await SharedPreferences.getInstance();
  var token = prefs.getString('token');
  final response = await http.get(
      Uri.parse('http://localhost:8000/subjects'),
      headers: 'x-access-token': token!);

  print(response.body);
  List<dynamic> list = "[" + response.body + "]" as List<dynamic>;
  List<Subject> subjectList = [];

  list.forEach((element) 
    subjectList.add(Subject.fromJson(element));
  );

  return subjectList;

这是处理传入数据的类(已更新 @Mofidul Islam):

class Subject 
  final String name;

  Subject(
    required this.name,
  );

  factory Subject.fromJson(Map<String, dynamic> json) 
    return Subject(name: json['NAME'] as String);
  

  parseJson(String responseBody) 
    final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>();
    return parsed.map<Subject>((json) => Subject.fromJson(json)).toList();
  

这是我的初始化状态:

void initState() 
    super.initState();    
    futureSubject = fetchSubject();
  

这就是我尝试显示数据的方式:

Widget build(BuildContext context) 
return MaterialApp(
  debugShowCheckedModeBanner: false,
  title: 'Materias',
  theme: ThemeData(
    primarySwatch: Colors.green,
  ),
  home: Scaffold(
    appBar: AppBar(
      title: const Text('Materias'),
    ),
    body: Center(
      child: FutureBuilder<List<Subject>>(
        future: futureSubject,
        builder: (context, snapshot) 
          if (snapshot.hasData) 
            return Column(
              children: snapshot.data!
                  .map((subject) => Text(subject.name))
                  .toList(),
            );
           else if (snapshot.hasError) 
            return Text('$snapshot.error');
          
          return const CircularProgressIndicator();
        ,
  

),
    ),
  ),
);

但是,页面加载时唯一显示的是:

Matematicas

我正在努力实现两件事:

    以列表方式显示数据,例如:
Subject Name 
Matematicas 
Naturales 
Ciencias Sociales 
Lenguaje Religion
    能够在点击时将它们用作另一个页面的链接

PD:如果我在return Subject.fromJson(jsonDecode(response.body)[0]); 上删除索引访问[0] 我得到Expected a value of type Map&lt;String, dynamic&gt; but got one of type List&lt;dynamic&gt;

关于如何完成此操作的任何建议或指南?

感谢您的宝贵时间

【问题讨论】:

【参考方案1】:

你需要循环播放它

parseJson(String responseBody) 
    final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>();
    return parsed
        .map<Subject>((json) => Subject.fromJson(json))
        .toList();
  

并将您的 api 调用更改为此

Future<List<Subject>> fetchSubject() async 
  .....
  return parseJson(json.encode(response.body));

对不起我的英语。

【讨论】:

我试过这个,但我在哪里打电话parseJson()?如果我尝试在 Future&lt;List&lt;Subject&gt;&gt; 方法中调用它,则表示该函数未定义。很抱歉花了这么长时间来回答,非常感谢您的帮助【参考方案2】:

请试试这个并从api方法返回列表

Future<List<Subject>> fetchSubject() async 
  var url = Uri.http('localhost:8000', "/subjects");
  var prefs = await SharedPreferences.getInstance();
  var token = prefs.getString('token');
  final response = await http.get(Uri.parse('http://localhost:8000/subjects'),
      headers: 'x-access-token': token!);
List<dynamic>list=response.body as List<dynamic>;
      List<Subject>subjectList=[];
        
      list.forEach((element)
        subjectList.add(Subject.fromJson(element));
      );

      return subjectList;
  

像这样重构 UI

Center(
          child: FutureBuilder<List<Subject>>(
            future: futureSubject,
            builder: (context, snapshot) 
              if (snapshot.hasData) 
                return Column(children: snapshot.data.map((subject)=>Text(subject.name)).toList(),);
               else if (snapshot.hasError) 
                return Text('$snapshot.error');
              
              return const CircularProgressIndicator();
            ,
          ),
        )

【讨论】:

我从 api 方法 Future&lt;Subject&gt;fetchSubject() 中尝试了这个,我以这种方式返回它 return subjectList[0],当我运行应用程序时,我得到 Expected value ot type List&lt;dynamic&gt; but got one of String。如果我尝试按照您提到的方式返回它,subject[0].name 我会在返回子句中收到此错误:A value of type 'String' can't be returned from the function 'fetchSubject' because it has a return type of 'Future&lt;List&lt;Subject&gt;&gt;'.。也许我错过了什么。 您应该返回 subjectList 而不是 subjectList[0] 并且函数返回类型应该是 Future> 而不是 Future 并重构您的 ui 以接收 List 我已经修改了我的答案。请看看它是否有帮助@Irwin 谢谢,尝试了更新的例子,我得到了Expected a value of type List&lt;dynamic&gt; but got one of String。我不得不提到我必须在return Column(children: snapshot.data.map((subject)=&gt;Text(subject.name)).toList(),); 中添加一个! 虽然我知道我做错了什么...... 元素不是 String 。它的 Map 像 "Name":"Mathermaticts"

以上是关于在 Flutter 中显示 JSON 数据的主要内容,如果未能解决你的问题,请参考以下文章

在 Flutter 中动态显示数据表布局中的 JSON 数据

flutter学习二:资源文件images

我想在 Flutter App 的 Listview 中显示我的 Json 数据

Flutter:显示来自 json 的数据

如何制作像生物编辑器一样的 Tinder - Flutter

将 JSON 数据显示到 DataTable Flutter