Flutter(二十)——JSON解析
前言
前一篇博文已经详细介绍了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
- 点赞
- 收藏
- 关注作者
评论(0)