在使用flutter开发应用时,有时候我们使用异步请求返回的数据,但是异步请求返回的数据是json格式的,flutter不像js一样可以直接将js转换为对象,从而直接使用。
那flutter如何解析或者说是使用json数据呢?
flutter解析json数据,是指使用 dart:convert 库中内置的 JSON 解码器,将 JSON 字符串解析成自定义对象的过程。使用这种方式,我们需要先将 JSON 字符串传递给 JSON.decode 方法解析成一个 Map,然后把这个 Map 传给自定义的类,进行相关属性的赋值。
本质如下:
这个过程在js或者其他语言中比较好解决。
但在flutter中需要如下操作,这些操作是使用flutter的基本功所有必须要熟练掌握,有如下步骤:
1、将json数据交个JSON.decode将其转化为一个Map类型的数据。
2、将Map数据转化为自定义对象。
如何转化为自定义的对象,这里有一个通用方法,先根据自己要使用的数据定义自定义类,自定义类中定义工厂函数,函数内部将Map中需要的数据赋值给实例对象。
所以流程图我们可以这样更新一下:
所以我们的步骤可以更新为:
1、将json数据交个JSON.decode将其转化为一个Map类型的数据。
2、定义自定义类,类的内定义工厂函数
3、将Map数据传入类的工厂函数得到最终数据
这里面还有几个问题:
1、定义的类是什么样的?
2、工厂函数是什么样子的。
接下来咱们来看个例子:假设页面要渲染如下一个json字符串数据,这样的数据通常是异步请求返回的结果:
String jsonString = '''
"id":"123",
"name":"张三",
"score" : 95
''';
首先我们要将字符串转换成Map格式数据(flutter里面的Map类似js里面字面量对象),然后将Map格式数据交给自定义类的工厂函数进行解析,然后再组成一个新的数组。
这里要注意flutter的Map格式数据类似js里面的字面量对象,但是访问时只能通过[key]的方式才能访问其属性。而字面量对象可以通过点的当时来访问其属性,总之flutter里面Map格式的数据和对象格式的数据是有严格区分的,而js中这一点不是很严格,这点大家要注意。
这里穿插一个实验,我们在dart中分别打印对象、json字符串对象、map数据看最终打印结果:
字符串可以通过json.decode(jsonString)方法转化为Map格式的数据。
String jsonString = '''
"id":"123",
"name":"张三",
"score" : 95
final jsonResponse = json.decode(str);
Map格式的数据可以通过[key]的当时访问,得到Map数据格式后,我们来定义自定义类,并且这个自定义类上面有工厂函数。
定义的Student的类如下:
class Student {
String id;
String name;
String score;
Student({this.id, this.name, this.score});
factory Student.fromjson(data) {
Student stu = new Student();
stu.id = data['id'];
stu.name = data['name'];
stu.score = data['score'];
return stu;
}
最终代码如下:
String jsonString = '''
"id":"123",
"name":"张三",
"score" : 95
final jsonResponse = json.decode(str);
class Student {
String id;
String name;
String score;
Student({this.id, this.name, this.score});
factory Student.fromjson(data) {
Student stu = new Student();
stu.id = data['id'];
stu.name = data['name'];
stu.score = data['score'];
return stu;
Student stu = Student.fromjson(jsonResponse);
print(stu);
这样就将json格式的字符串转换成了flutter对象的实例。
进阶部分,如果json格式的字符串中的某一个属性的值不是普通值而是对象,格式如下:
final String str = '''{
"id":"123",
"name":"张三",
"score" : 95,
"teacher": {
"name": "李四",
"age" : 40
}''';
我们发现新增的teacher属性的值是一个对象,该咋办呢?这里的需要针对teacher单独定义一个类Teacher,代码如下:
class Teacher {
String name;
int age;
Teacher({this.name, this.age});
factory Teacher.fromjson(data) {
Teacher teacher = new Teacher();
teacher.name = data['name'];
teacher.age = data['age'];
return teacher;
}
之后将Student类改造:
class Student {
String id;
String name;
int score;
Teacher teacher;
Student({this.id, this.name, this.score,this.teacher});
factory Student.fromjson(data) {
Student stu = new Student();
stu.id = data['id'];
stu.name = data['name'];
stu.score = data['score'];
stu.teacher = Teacher.fromjson(data['teacher']);
return stu;
}
最终代码结果如下:
final String str = '''{
"id":"123",
"name":"张三",
"score" : 95,
"teacher": {
"name": "李四",
"age" : 40
}''';
class Teacher {
String name;
int age;
Teacher({this.name, this.age});
factory Teacher.fromjson(data) {
Teacher teacher = new Teacher();
teacher.name = data['name'];
teacher.age = data['age'];
return teacher;
class Student {
String id;
String name;
int score;
Teacher teacher;
Student({this.id, this.name, this.score,this.teacher});
factory Student.fromjson(data) {
Student stu = new Student();
stu.id = data['id'];
stu.name = data['name'];
stu.score = data['score'];
stu.teacher = Teacher.fromjson(data['teacher']);
return stu;
Student stu = Student.fromjson(jsonResponse);
print(stu.teacher.age);
再次进阶,以上只是解析json对象,如果是json数组呢?
代码如下:
final String str = '''[
"id":"123",
"name":"张三",
"score" : 95,
"teacher": {
"name": "李四",
"age" : 40
"id":"123",
"name":"张三",
"score" : 95,
"teacher": {
"name": "李四",
"age" : 40
"id":"123",
"name":"张三",
"score" : 95,
"teacher": {
"name": "李四",
"age" : 40
]''';
如果是字符串呢,该咋办?很简单遍历上面的数组即可。代码如下:
var jsonResponse = json.decode(str);
List list = [];
for (dynamic data in jsonResponse) {
Student student = Student.fromjson(data);
list.add(student);