Flutter 中的 JSON 解析

文章讲述了在Flutter中处理复杂JSON数据时遇到的问题,涉及动态类型转换、从JSON解析模型类,以及如何处理嵌套的对象数组。作者通过实例演示了解决List到具体类型转换的方法,如List或自定义对象列表。
摘要由CSDN通过智能技术生成

然后我们在 main() 中去调用 decodeCountry() 运行,报错了…

Unhandled Exception: type ‘List’ is not a subtype of type ‘List’

错误日志说 List<dynamic> 不是 List<String> 的子类型,也就是我们在country的实体类中直接给 cities 属性赋值为 cities: json['cities'],我们先来看看 json['cities'] 是什么类型:

factory Country.fromJson(Map<String, dynamic> json) {
print(‘json[“cities”] type is ${json[‘cities’].runtimeType}’);
return Country(name: json[‘name’], cities: json[‘cities’]);
}

输出如下:

flutter: json[“cities”] type is List

这个时候我们需要将 Country.fromJson(...) 方法作如下更改:

factory Country.fromJson(Map<String, dynamic> json) {
print(‘json[“cities”] type is ${json[‘cities’].runtimeType}’);
var originList = json[‘cities’];
List cityList = new List.from(originList);
return Country(name: json[‘name’], cities: cityList);
}

上述代码中,我们创建了一个 List<String> 类型的数组,然后将 List<dynamic> 数组中的元素都添加到了 List<String> 中。输出如下:

flutter: json[“cities”] type is List
flutter: country name is China

对象嵌套

定义一个 shape.json ,格式如下:

{
“name”: “rectangle”,
“property”: {
“width”: 5.0,
“height”: 10.0
}
}

实体如下:

class Shape {
String name;
Property property;

Shape({this.name, this.property});

factory Shape.fromJson(Map<String, dynamic> json) {
return Shape(name: json[‘name’], property: json[‘property’]);
}
}

class Property {
double width;
double height;

Property({this.width, this.height});

factory Property.fromJson(Map<String, dynamic> json) {
return Property(width: json[‘width’], height: json[‘height’]);
}
}

Service 类如下:

import ‘dart:async’;
import ‘dart:convert’;
import ‘package:flutter/services.dart’;
import ‘…/models/shape.dart’;

Future _loadShapeJson() async {
return await rootBundle.loadString(‘assets/shape.json’);
}

Future decodeShape() async {
String shapeJson = await _loadShapeJson();

Map<String, dynamic> jsonMap = json.decode(shapeJson);

Shape shape = Shape.fromJson(jsonMap);

print(‘shape name is ${shape.name}’);
return shape;
}

运行之后,会报如下错误:

Unhandled Exception: type ‘_InternalLinkedHashMap<String, dynamic>’ is not a subtype of type ‘Property’

也就是说 property: json['property'] 这里赋值的类型是 _InternalLinkedHashMap<String, dynamic> 而不是 Propertyjson['property'] 的值是这样的 {width: 5.0, height: 10.0},它是一个 Map ,并不是一个 Property 对象,我们需要先将这个 Map 转化为对象,然后在赋值:

factory Shape.fromJson(Map<String, dynamic> json) {
print(‘json[“property”] is ${json[‘property’]}’);
Property property = Property.fromJson(json[‘property’]); // new line
return Shape(name: json[‘name’], property: property);
}

输出:

shape name is rectangle

复杂的对象数组嵌套

{
“id”: “0302”,
“class_name”: “三年二班”,
“students”: [
{
“name”: “叶湘伦”,
“sex”: “男”
},
{
“name”: “路小雨”,
“sex”: “女”
}
]
}

实体:

class ClassInfo {
String id;
String name;
List studentList;

ClassInfo({this.id, this.name, this.studentList});

factory ClassInfo.fromJson(Map<String, dynamic> json) {
return ClassInfo(
id: json[‘id’],
name: json[‘class_name’],
studentList: json[‘students’]);
}
}

class Student {
String name;
String sex;

Student({this.name, this.sex});

factory Student.fromJson(Map<String, dynamic> json) {
return Student(name: json[‘name’], sex: json[‘sex’]);
}
}

service:

import ‘dart:async’;
import ‘dart:convert’;
import ‘package:flutter/services.dart’;
import ‘…/models/class_info.dart’;

Future _loadClassInfoJson() async {
return await rootBundle.loadString(‘assets/class_info.json’);
}

Future decodeClassInfo() async {
String classInfoJson = await _loadClassInfoJson();

Map<String, dynamic> jsonMap = json.decode(classInfoJson);

ClassInfo classInfo = ClassInfo.fromJson(jsonMap);
classInfo.studentList
.forEach((student) => print(‘student name is ${student.name}’));
return classInfo;
}

上述代码在运行后还是会报错:

Unhandled Exception: type ‘List’ is not a subtype of type ‘List’

同样,还是在 studentList: json['students'] 出问题了,我们把 json['students'] 的输出来看看:

[{name: 叶湘伦, sex: 男}, {name: 路小雨, sex: 女}]

上述结果的类型为 List<dynamic> 。现在我们需要将 List<dynamic> 转换到一个 List<Student> 类型的数组中,这里需要用到一个操作符 mapmap 操作符的作用就是将某种类型转换为另一种类型。如下:

factory ClassInfo.fromJson(Map<String, dynamic> json) {
final originList = json[‘students’] as List;
List studentList =
originList.map((value) => Student.fromJson(value)).toList();
return ClassInfo(
id: json[‘id’], name: json[‘class_name’], studentList: studentList);
}

输出:

flutter: student name is 叶湘伦
flutter: student name is 路小雨

单纯的数组

member.json

[
{
“id”: 1,
“name”: “Jack”
},
{
“id”: 2,
“name”: “Rose”
},
{
“id”: 3,
“name”: “Karl”
}
]

实体:

class MemberList {
List memberList;

MemberList({this.memberList});

factory MemberList.fromJson(List listJson) {

List memberList =
listJson.map((value) => Member.fromJson(value)).toList();

return MemberList(memberList: memberList);
}
}

class Member {
int id;
String name;

Member({this.id, this.name});

factory Member.fromJson(Map<String, dynamic> json) {
return Member(id: json[‘id’], name: json[‘name’]);
}
}

因为 member.json 是一个单纯的数组,所以上述代码中我们创建了一个 MemberList 类来将这个 Member 数组包含起来。

注意下上述代码中 MemberList.fromJson(...) 中的写法。

service:

import ‘dart:async’;
import ‘package:flutter/services.dart’;
import ‘dart:convert’;
import ‘…/models/member.dart’;

Future _loadMemberJson() async {
return await rootBundle.loadString(‘assets/member.json’);
}

Future decodeMemberList() async {
String memberListJson = await _loadMemberJson();

List list = json.decode(memberListJson);

MemberList memberList = MemberList.fromJson(list);

memberList.memberList
.forEach((member) => print(‘member name is ${member.name}’));

return memberList;
}

输出:

flutter: member name is Jack
flutter: member name is Rose
flutter: member name is Karl

复杂的 Json 解析

之前的文章 Flutter 中 ListView 的使用 中用到了 豆瓣API ,这个 API 中返回的数据包含了当前热播的电影,大家尝试着按需解析一下吧 !!!
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
如有错误,还请指出。谢谢!!!
源码地址
参考链接:
medium.com/flutter-com…
github.com/flutter/flu…

最后

跳槽季整理面试题已经成了我多年的习惯!在这里我和身边一些朋友特意整理了一份快速进阶为Android高级工程师的系统且全面的学习资料。涵盖了Android初级——Android高级架构师进阶必备的一些学习技能。

附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)


《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
roid高级工程师的系统且全面的学习资料。涵盖了Android初级——Android高级架构师进阶必备的一些学习技能。**

附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

[外链图片转存中…(img-hZsdNUqP-1714959116049)]
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值