Flutter(二十)——JSON解析

举报
择城终老 发表于 2021/07/26 23:53:30 2021/07/26
【摘要】 本文目录 前言JSON转换成Dart对象实践根据JSON用工具生成实体类当JSON类属性与服务器返回属性不一致时 前言 前一篇博文已经详细介绍了Flutter开发中的网络请求,但其实大多数项目中,返回HTML内容是不够的,因为移动端使用的最多的请求是JSON数据,所以我们需要掌握Flutter开发中,JSON解析的知识。JSON(javaScr...

前言

前一篇博文已经详细介绍了Flutter开发中的网络请求,但其实大多数项目中,返回HTML内容是不够的,因为移动端使用的最多的请求是JSON数据,所以我们需要掌握Flutter开发中,JSON解析的知识。JSON(javaScript Object Notation,JS对象简谱)是一种轻量级的数据交换格式)

JSON转换成Dart对象

假设,我们现在是开发的是一款新闻App,通过访问相关的接口之后,服务器返回了这样一条简单的JSON数据,如下图所示:

{"title":"疫情疫苗出世,多板块重大利好"}

  
 
  • 1

那么我们应该如何处理这条数据显示在界面上呢?相信有过Java开发Android经验的读者,肯定知道如何把这段数据还原成一个对象,并且在界面显示出来。同样,在Flutter开发中,也可以把这个JSON数据转换为Dart对象,我们先定义Dart对象News,代码如下:

class News{
  final String title; News({this.title}); factory News.fromJson(Map<String,dynamic> json){ return News( title: json['title'], );
  }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

在dart:convert里面有一个JSON常量,它是负责处理服务端返回的JSON数据的,在请求响应回来的时,通过json.decode(response.body)方法调用可以把JSON结果转换城Map类型或List类型。如果是一个JSON对象,返回将是一个Map;如果是JSON数组,则会返回List。

上面代码之所以把map的value定义成dynamic,是因为不肯定value的类型,毕竟有可能是字符串,有可能是整型,还是用这个自动匹配类型最实在。

实践

在JSON解析之后,我们需要把结果通过界面的形式展现给用户看,所以下面我们直接来实现其功能:

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key); final String title; @override
  _MyHomePageState createState() => _MyHomePageState(news: httpPost());
}

class _MyHomePageState extends State<MyHomePage> { final Future<News> news;
  _MyHomePageState({Key key,this.news}); @override
  Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("HttpClient"), ), body:Center( child: FutureBuilder<News>( future: news, builder: (context,snapshot){ if(snapshot.hasData){ return Text(snapshot.data.title); }else if(snapshot.hasError){ return Text("错误啦"); } return CircularProgressIndicator(); }, ), ), );
  }
}

Future<News> httpPost() async{
  final response=await http.get("http://liyuanjinglyj.com/demo/");
  if(response.statusCode==200){ print(utf8.decode(response.bodyBytes)); return News.fromJson(json.decode(response.body));
  }else{ throw Exception('请求不到JSon');
  }

}

class News{
  final String title; News({this.title}); factory News.fromJson(Map<String,dynamic> json){ return News( title: json['title'], );
  }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59

代码很简单,这里专门定义了一个JSON的Dart类,用于处理JSON数据,同时用FutureBuilder组件将JSON显示在屏幕上。显示效果首图所示。

根据JSON用工具生成实体类

上面可以说是静态生成JSON格式,也就是说手动定义了一个JSON类,但是假如有许多许多JSON格式的数据,那怎么获取JSON数据呢?一个一个写肯定麻烦的很,所以我们需要借助工具去自动生成JSON类,这里就也需要在pubspec.yaml中导入依赖:

dependencies:
  json_annotation: ^2.0.0

dev_dependencies:
  build_runner: ^1.0.0
  json_serializable: ^2.0.0

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

然后我们创建一个实体类,格式如下:

import 'package:json_annotation/json_annotation.dart';

part 'user.g.dart';

@JsonSerializable()
class User{
  String name;
  String email;
  User({this.name,this.email}); factory User.fromJson(Map<String,dynamic> json)=>_$UserFromJson(json); Map<String,dynamic> toJson=>_$UserToJson(this);
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

这里会报错,特别是part ‘user.g.dart’;与最后两句,都会出现红色的波浪线提示,但这是正常的不用急,我们可以把上面的代码看成是模板,然后我们在工程目录文件下输入如下命令:

flutter packages pub run build_runner build

  
 
  • 1

输入完这个命令之后,就会生成一个user.g.dart文件,在user.dart同级目录之中,代码如下:

// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'user.dart';

// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************

User _$UserFromJson(Map<String, dynamic> json) {
  return User(name: json['name'] as String, email: json['email'] as String);
}

Map<String, dynamic> _$UserToJson(User instance) => <String, dynamic>{'name': instance.name, 'email': instance.email};

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

博主为了直观,所以减少了许多参数,但在实际情况中,JSON的参数肯定会有很多,甚至还有层级,那么这种情况下,这样自动生成起来肯定比较方便,也比较节约时间。

输入效果

但这种方式也会有一个缺陷,就是假如我的JSON格式变更了,那还不得一次一次生成?很显然,Flutter也考虑到这种情况,所以提供给我们一种监听模式来实现每一次的生成,命令如下:

flutter packages pub run build_runner watch

  
 
  • 1

这个命令只需要执行一次,那么就会一直监听在后台运行,在也不要我们操作什么就可以自动生成了。

当JSON类属性与服务器返回属性不一致时

虽然说上面的操作很方便,但自动生成还有一个待解决的问题,那么就是当自己的JSON类与服务器端返回的字段不一致的时候怎么办?当然你可以直接更改字段,但可能一改就要动全部的内容,所以这个时候使用JsonKey注解的方式就比较高效了,比如:

@JsonKey(name:'user_name')
final String userName;

  
 
  • 1
  • 2

这样注解加自动生成JSON类就非常完美高效,可以大大提高程序的开发效率。

文章来源: liyuanjinglyj.blog.csdn.net,作者:李元静,版权归原作者所有,如需转载,请联系作者。

原文链接:liyuanjinglyj.blog.csdn.net/article/details/104168589

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。