Flutter开发-02-复杂JSON数据和序列化在Flutter中的最佳实践

系列文章目录

Flutter开发-01-简单JSON数据和序列化在Flutter中的最佳实践

Flutter开发-02-复杂JSON数据和序列化在Flutter中的最佳实践

前言

本节是春节前最后一篇技术文章了,节后再更新技术相关的文章以及非技术相关的文章,本来是想梳理一下年终总结的,因为比较忙,就先不总结了,节后梳理一篇新年规划文章,然后总结下今年的工作学习生活的一些片段吧。(也不一定,der~)

之前简单介绍了对于简单JSON数据的解析与序列化的一些方法,我们了解到了在Dart语言中的JSON数据以及解析方法,可以和移动端的解析方法进行对比学习。这一节将对于复杂JSON数据结构的解析,本文介绍以下三种方法。


一、解析assets文件夹下的本地json数据?

在assets目录下新建一个user_list.json文件,Json数据结构为:

json 复制代码
{
  "code":0,
  "message":"Success",
  "data":[
    {
      "name":"Jerry",
      "email":"Jerry@example.com"
    },
    {
      "name":"Alex",
      "email":"Alex@example.com"
    },
    {
      "name":"Tom",
      "email":"Tom@example.com"
    },
    {
      "name":"Jack",
      "email":"Jack@example.com"
    },
    {
      "name":"Lucy",
      "email":"Lucy@example.com"
    }
  ]
}

可以看到这是一个包含数组的的JSON对象,对于这样类型的JSON数据的解析方法有多种; 首先介绍下Flutter中解析本地数据的方法:

dart 复制代码
Future decodeAssetJson() async {
    // 解析本地数据-List数组
    Map<String, dynamic> userListMap =
        await loadJsonAssets("assets/user_list.json");

    if (kDebugMode) {
      print('\n =======================解析数组开始========================== \n ');
      // userListMap : {code: 0, message: Success, users: [{name: Jerry, email: Jerry@example.com}, {name: Alex, email: Alex@example.com}, {name: Tom, email: Tom@example.com}]}
      print('userListMap  : $userListMap');
      // userListMap toString : {code: 0, message: Success, users: [{name: Jerry, email: Jerry@example.com}, {name: Alex, email: Alex@example.com}, {name: Tom, email: Tom@example.com}]}
      print('userListMap toString : ${userListMap.toString()}');
      // userListMap jsonEncode :  {"code":0,"message":"Success","users":[{"name":"Jerry","email":"Jerry@example.com"},{"name":"Alex","email":"Alex@example.com"},{"name":"Tom","email":"Tom@example.com"}]}
      print('userListMap jsonEncode :  ${jsonEncode(userListMap)}');
    }
}

注意:对于耗时操作,需要将这部分工作移交到单独的 isolate 中.

输出日志:

dart 复制代码
userListMap  : {code: 0, message: Success, data: [{name: Jerry, email: Jerry@example.com}, {name: Alex, email: Alex@example.com}, {name: Tom, email: Tom@example.com}, {name: Jack, email: Jack@example.com}, {name: Lucy, email: Lucy@example.com}]}

userListMap toString : {code: 0, message: Success, data: [{name: Jerry, email: Jerry@example.com}, {name: Alex, email: Alex@example.com}, {name: Tom, email: Tom@example.com}, {name: Jack, email: Jack@example.com}, {name: Lucy, email: Lucy@example.com}]}

userListMap jsonEncode :  {"code":0,"message":"Success","data":[{"name":"Jerry","email":"Jerry@example.com"},{"name":"Alex","email":"Alex@example.com"},{"name":"Tom","email":"Tom@example.com"},{"name":"Jack","email":"Jack@example.com"},{"name":"Lucy","email":"Lucy@example.com"}]}

二、解析复杂JSON数据

1.类型1:解析带有数组的JSON数据

json 复制代码
{
  "code":0,
  "message":"Success",
  "data":[
    {
      "name":"Jerry",
      "email":"Jerry@example.com"
    },
    {
      "name":"Alex",
      "email":"Alex@example.com"
    },
    {
      "name":"Tom",
      "email":"Tom@example.com"
    },
    {
      "name":"Jack",
      "email":"Jack@example.com"
    },
    {
      "name":"Lucy",
      "email":"Lucy@example.com"
    }
  ]
}

(1)、方式一:将整个json数据序列化,创建user_list.dart文件,序列化JSON数据:

dart 复制代码
// To parse this JSON data, do
//
//     final userList = userListFromJson(jsonString);

import 'dart:convert';
import 'user.dart';

UserList userListFromJson(String str) => UserList.fromJson(json.decode(str));

String userListToJson(UserList data) => json.encode(data.toJson());

class UserList {
  int code;
  String message;
  List<User> data;

  UserList({
    required this.code,
    required this.message,
    required this.data,
  });

  factory UserList.fromJson(Map<String, dynamic> json) => UserList(
        code: json["code"],
        message: json["message"],
        data: List<User>.from(json["data"].map((x) => User.fromJson(x))),
      );

  Map<String, dynamic> toJson() => {
        "code": code,
        "message": message,
        "data": List<dynamic>.from(data.map((x) => x.toJson())),
      };
}

其中,User还是使用之前建立的User.dart对象:

dart 复制代码
/// YApi QuickType插件生成,具体参考文档:https://plugins.jetbrains.com/plugin/18847-yapi-quicktype/documentation

import 'dart:convert';

User userFromJson(String str) => User.fromJson(json.decode(str));

String userToJson(User data) => json.encode(data.toJson());

class User {
    User({
        required this.name,
        required this.email,
    });

    String name;
    String email;

    factory User.fromJson(Map<String, dynamic> json) => User(
        name: json["name"],
        email: json["email"],
    );

    Map<String, dynamic> toJson() => {
        "name": name,
        "email": email,
    };
}

直接解析整个JSON返回数据,去获取需要的List:

dart 复制代码
Future decodeAssetJson() async {
    // 解析本地数据-List数组
    Map<String, dynamic> userListMap =
        await loadJsonAssets("assets/user_list.json");
        
    // 方法1 : 整个JSON串解析成Model对象
    var userListBean = UserList.fromJson(userListMap);

    if (kDebugMode) {
      print('\n =======================解析数组开始1========================== \n ');
      // UserList toString : Instance of 'UserList'
      print('UserList toString : ${userListBean.toString()}');
      // UserList toJson : {code: 0, message: Success, users: [{name: Jerry, email: Jerry@example.com}, {name: Alex, email: Alex@example.com}, {name: Tom, email: Tom@example.com}]}
      print('UserList toJson : ${userListBean.toJson()}');

      var users = userListBean.data;

      if (users.isNotEmpty) {
        for (int i = 0; i < (users.length); i++) {
          // UserList  : => 0   [Instance of 'User', Instance of 'User', Instance of 'User']
          // UserList  : => 1   [Instance of 'User', Instance of 'User', Instance of 'User']
          // UserList  : => 2   [Instance of 'User', Instance of 'User', Instance of 'User']
          print('UserList  : => $i   $users');
          // UserList toString : => 0   Instance of 'User'
          // UserList toString : => 1   Instance of 'User'
          // UserList toString : => 2   Instance of 'User'
          print('UserList toString : => $i   ${users[i].toString()}');
          // UserList toJson : => 0   {name: Jerry, email: Jerry@example.com}
          // UserList toJson : => 1   {name: Alex, email: Alex@example.com}
          // UserList toJson : => 2   {name: Tom, email: Tom@example.com}
          print('UserList toJson : => $i   ${users[i].toJson()}');
          // UserList jsonEncode : => 0   {"name":"Jerry","email":"Jerry@example.com"}
          // UserList jsonEncode : => 1   {"name":"Alex","email":"Alex@example.com"}
          // UserList jsonEncode : => 2   {"name":"Tom","email":"Tom@example.com"}
          print('UserList jsonEncode : => $i   ${jsonEncode(users[i])}');
          // UserList name : => 0   Jerry
          // UserList name : => 1   Alex
          // UserList name : => 2   Tom
          print('UserList name : => $i   ${users[i].name}');
          // UserList email : => 0   Jerry@example.com
          // UserList email : => 1   Alex@example.com
          // UserList email : => 2   Tom@example.com
          print('UserList email : => $i   ${users[i].email}');
        }
      }
      print('\n =======================解析数组结束1========================== \n ');
    }
}

输出日志:

dart 复制代码
UserList toString : Instance of 'UserList'
UserList toJson : {code: 0, message: Success, data: [{name: Jerry, email: Jerry@example.com}, {name: Alex, email: Alex@example.com}, {name: Tom, email: Tom@example.com}, {name: Jack, email: Jack@example.com}, {name: Lucy, email: Lucy@example.com}]}
UserList  : => 0   [Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User']
UserList toString : => 0   Instance of 'User'
UserList toJson : => 0   {name: Jerry, email: Jerry@example.com}
UserList jsonEncode : => 0   {"name":"Jerry","email":"Jerry@example.com"}
UserList name : => 0   Jerry
UserList email : => 0   Jerry@example.com

...

(2)、方式二:只获取返回对象中的List数组

dart 复制代码
Future decodeAssetJson() async {
    // 解析本地数据-List数组
    Map<String, dynamic> userListMap =
        await loadJsonAssets("assets/user_list.json");
	
	// 方法2: 只获取返回对象中的List数组
    if (kDebugMode) {
      var usersMap = userListMap["data"];
      print('\n =======================解析数组开始2========================== \n ');
      // usersMap :  [{name: Jerry, email: Jerry@example.com}, {name: Alex, email: Alex@example.com}, {name: Tom, email: Tom@example.com}]
      print('usersMap :  $usersMap');
      // usersMap toString:  [{name: Jerry, email: Jerry@example.com}, {name: Alex, email: Alex@example.com}, {name: Tom, email: Tom@example.com}]
      print('usersMap toString:  ${usersMap.toString()}');

      // jsonEncode转换字符串
      String userMapJson = jsonEncode(usersMap);

      // userMapJson jsonEncode:  [{"name":"Jerry","email":"Jerry@example.com"},{"name":"Alex","email":"Alex@example.com"},{"name":"Tom","email":"Tom@example.com"}]
      print('userMapJson jsonEncode:  $userMapJson');

      // 列表转换时一定要加一下强转List<dynamic>,否则会报错
      var list = usersMap.map((e) => User.fromJson(e)).toList();

      // UserList-list :  [Instance of 'User', Instance of 'User', Instance of 'User']
      print('UserList-list :  $list');
      // UserList-list toString:  [Instance of 'User', Instance of 'User', Instance of 'User']
      print('UserList-list toString:  ${list.toString()}');
      print('UserList-list toJson:  ${jsonEncode(list)}');

      if (list.isNotEmpty) {
        for (int i = 0; i < (list.length); i++) {
          // UserList : => 0   Instance of 'User'
          print('UserList  : => $i   ${list[i].toString()}');
          // UserList toString : => 0   Instance of 'User'
          print('UserList toString : => $i   ${list[i].toString()}');
          // UserList toJson : => 0   {name: Jerry, email: Jerry@example.com}
          print('UserList toJson : => $i   ${list[i].toJson()}');
          // UserList jsonEncode : => 0   {"name":"Jerry","email":"Jerry@example.com"}
          print('UserList jsonEncode : => $i   ${jsonEncode(list[i])}');
          // UserList name : => 0   Jerry
          print('UserList name : => $i   ${list[i].name}');
          // UserList email : => 0   Jerry@example.com
          print('UserList email : => $i   ${list[i].email}');
        }
      }
      print('\n =======================解析数组结束2========================== \n ');
    }
}

输出日志:

dart 复制代码
usersMap :  [{name: Jerry, email: Jerry@example.com}, {name: Alex, email: Alex@example.com}, {name: Tom, email: Tom@example.com}, {name: Jack, email: Jack@example.com}, {name: Lucy, email: Lucy@example.com}]
usersMap toString:  [{name: Jerry, email: Jerry@example.com}, {name: Alex, email: Alex@example.com}, {name: Tom, email: Tom@example.com}, {name: Jack, email: Jack@example.com}, {name: Lucy, email: Lucy@example.com}]
userMapJson jsonEncode:  [{"name":"Jerry","email":"Jerry@example.com"},{"name":"Alex","email":"Alex@example.com"},{"name":"Tom","email":"Tom@example.com"},{"name":"Jack","email":"Jack@example.com"},{"name":"Lucy","email":"Lucy@example.com"}]
UserList-list :  [Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User']
UserList-list toString:  [Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User']
UserList-list jsonEncode:  [{"name":"Jerry","email":"Jerry@example.com"},{"name":"Alex","email":"Alex@example.com"},{"name":"Tom","email":"Tom@example.com"},{"name":"Jack","email":"Jack@example.com"},{"name":"Lucy","email":"Lucy@example.com"}]
UserList  : => 0   Instance of 'User'
UserList toString : => 0   Instance of 'User'
UserList toJson : => 0   {name: Jerry, email: Jerry@example.com}
UserList jsonEncode : => 0   {"name":"Jerry","email":"Jerry@example.com"}
UserList name : => 0   Jerry
UserList email : => 0   Jerry@example.com

...

关键是需要把取到的数组map转换为序列化的User数组列表:

// 列表转换时一定要加一下强转List,否则会报错 var list = usersMap.map((e) => User.fromJson(e)).toList();

(2)、方式三:使用泛型创建BaseResponse基类

方法二不好的地方在于,如果解析的json字段非常的多,一个个的手动的去解析就非常麻烦,非常容易因为key值写错导致解析错误。使用 json_serializable 结合泛型,我们可以先写出数据返回的基类,这和Android原生开发的思路是一样的,对于后面结合网络请求,也是使用这种方式。

BaseResponse:

dart 复制代码
import 'package:json_annotation/json_annotation.dart';

part 'base_response.g.dart';

/// Time: 2023/9/4/0004 on 16:49
/// User: Jerry
/// Description: 根据服务器接口返回格式统一标准BaseResponse
/// 1、一次性代码生成
/// 通过在项目根目录运行命令 flutter pub run build_runner build --delete-conflicting-outputs,
/// 你可以在任何需要的时候为你的模型生成 JSON 序列化数据代码。这会触发一次构建,遍历源文件,选择相关的文件,
/// 然后为它们生成必须的序列化数据代码。 虽然这样很方便,但是如果你不需要在每次修改了你的模型类后都要手动构建那将会很棒。
/// 2、持续生成代码
/// 监听器 让我们的源代码生成过程更加方便。它会监听我们项目中的文件变化,并且会在需要的时候自动构建必要的文件。
/// 你可以在项目根目录运行 flutter pub run build_runner watch 启动监听。
/// 启动监听并让它留在后台运行是安全的。

/// 一个注释,用于代码生成器,使其知道该类需要生成JSON序列化逻辑
@JsonSerializable(genericArgumentFactories: true)
class BaseResponse<T> {
  //消息(例如成功消息文字/错误消息文字)
  String? message;

  bool? success = false;

  //自定义code(可根据内部定义方式)
  int? code;

  //接口返回的数据
  T? data;

  BaseResponse({
    this.message,
    this.success,
    this.code,
    this.data,
  });

  /// 从映射创建新BaseResponse实例所需的工厂构造函数。将映射传递给生成的' _BaseResponseFromJson() '构造函数。
  /// 构造函数以源类命名,在本例中为BaseResponse。
  factory BaseResponse.fromJson(
          Map<String, dynamic> json, T Function(dynamic json) fromJsonT) =>
      _$BaseResponseFromJson<T>(json, fromJsonT);

  /// ' toJson '是类声明支持序列化为JSON的约定。该实现仅仅调用私有的、生成的助手方法' _BaseResponseToJson '。
  Map<String, dynamic> toJson(Object? Function(T value) toJsonT) =>
      _$BaseResponseToJson<T>(this, toJsonT);
}

数据解析代码:

dart 复制代码
Future decodeAssetJson() async {
    // 解析本地数据-List数组
    Map<String, dynamic> userListMap =
        await loadJsonAssets("assets/user_list.json");

    // 列表转换时一定要加一下强转List<dynamic>,否则会报错:type 'List<dynamic>' is not a subtype of type 'List<User>'
    BaseResponse<List<User>> userListMap2 = BaseResponse.fromJson(
        userListMap,
        (json) => (json as List<dynamic>)
            // .map((e) => User.fromJson(e as Map<String, dynamic>))
            .map((e) => User.fromJson(e))
            .toList());

    var usersMap = userListMap2.data;

	if (kDebugMode) {
      print('\n =======================使用泛型解析开始========================== \n ');
      //  userListMap2  : Instance of 'BaseResponse<List<User>>'
      print('userListMap2*  : $userListMap2');
      print('userListMap2* message : ${userListMap2.message}');
      print('userListMap2* code : ${userListMap2.code}');
      print('userListMap2* data : ${userListMap2.data}');
      // userListMap2 toString : Instance of 'BaseResponse<List<User>>'
      print('userListMap2* toString : ${userListMap2.toString()}');

	  // usersMap :  [{name: Jerry, email: Jerry@example.com}, {name: Alex, email: Alex@example.com}, {name: Tom, email: Tom@example.com}]
      print('usersMap :  $usersMap');
      // usersMap toString:  [{name: Jerry, email: Jerry@example.com}, {name: Alex, email: Alex@example.com}, {name: Tom, email: Tom@example.com}]
      print('usersMap toString:  ${usersMap.toString()}');

      // jsonEncode转换字符串
      String userMapJson = jsonEncode(usersMap);

      // userMapJson jsonEncode:  [{"name":"Jerry","email":"Jerry@example.com"},{"name":"Alex","email":"Alex@example.com"},{"name":"Tom","email":"Tom@example.com"}]
      print('userMapJson jsonEncode:  $userMapJson');

      List<User>? list = userListMap2.data;

      // UserList-list :  [Instance of 'User', Instance of 'User', Instance of 'User']
      print('UserList-list :  $list');
      // UserList-list toString:  [Instance of 'User', Instance of 'User', Instance of 'User']
      print('UserList-list toString:  ${list.toString()}');

      if (list != null && list.isNotEmpty) {
        for (int i = 0; i < (list.length); i++) {
          // UserList : => 0   Instance of 'User'
          print('UserList  : => $i   ${list[i].toString()}');
          // UserList toString : => 0   Instance of 'User'
          print('UserList toString : => $i   ${list[i].toString()}');
          // UserList toJson : => 0   {name: Jerry, email: Jerry@example.com}
          print('UserList toJson : => $i   ${list[i].toJson()}');
          // UserList jsonEncode : => 0   {"name":"Jerry","email":"Jerry@example.com"}
          print('UserList jsonEncode : => $i   ${jsonEncode(list[i])}');
          // UserList name : => 0   Jerry
          print('UserList name : => $i   ${list[i].name}');
          // UserList email : => 0   Jerry@example.com
          print('UserList email : => $i   ${list[i].email}');
        }
      }
    }
}

核心代码:

dart 复制代码
BaseResponse<List<User>> userListMap2 = BaseResponse.fromJson(
        userListMap,
        (json) => (json as List<dynamic>)
            // .map((e) => User.fromJson(e as Map<String, dynamic>))
            .map((e) => User.fromJson(e))
            .toList());

    var usersMap = userListMap2.data;

1、 列表转换时一定要加一下强转List,否则会报错:type 'List' is not a subtype of type 'List'; 2、使用.toList将map转换为对应的User对象列表;

输出日志:

dart 复制代码
userListMap2*  : Instance of 'BaseResponse<List<User>>'
userListMap2* message : Success
userListMap2* code : 0
userListMap2* data : [Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User']
userListMap2* toString : Instance of 'BaseResponse<List<User>>'
usersMap :  [Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User']
usersMap toString:  [Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User']
userMapJson jsonEncode:  [{"name":"Jerry","email":"Jerry@example.com"},{"name":"Alex","email":"Alex@example.com"},{"name":"Tom","email":"Tom@example.com"},{"name":"Jack","email":"Jack@example.com"},{"name":"Lucy","email":"Lucy@example.com"}]
UserList-list :  [Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User']
UserList-list toString:  [Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User']
UserList-list jsonEncode:  [{"name":"Jerry","email":"Jerry@example.com"},{"name":"Alex","email":"Alex@example.com"},{"name":"Tom","email":"Tom@example.com"},{"name":"Jack","email":"Jack@example.com"},{"name":"Lucy","email":"Lucy@example.com"}]
UserList  : => 0   Instance of 'User'
UserList toString : => 0   Instance of 'User'
UserList toJson : => 0   {name: Jerry, email: Jerry@example.com}
UserList jsonEncode : => 0   {"name":"Jerry","email":"Jerry@example.com"}
UserList name : => 0   Jerry
UserList email : => 0   Jerry@example.com

...

2.类型2:解析带有分页类型数组的JSON数据

如果是这种分页的带有数组的JSON数据类型,可以按照下面的方法进行数据解析:user_list2.json

json 复制代码
{
  "data":{
    "curPage":1,
    "datas":[
      {
        "name":"肖战",
        "email":"肖战@example.com"
      },
      {
        "name":"丁程鑫",
        "email":"丁程鑫@example.com"
      },
      {
        "name":"贺峻霖",
        "email":"贺峻霖@example.com"
      },
      {
        "name":"李天泽",
        "email":"李天泽@example.com"
      },
      {
        "name":"刘耀文",
        "email":"刘耀文@example.com"
      },
      {
        "name":"成毅",
        "email":"成毅@example.com"
      }
    ],
    "offset":0,
    "over":false,
    "pageCount":3,
    "size":20,
    "total":46
  },
  "code":0,
  "message":"Success get"
}

仔细观察 user_list.jsonuser_list2.json,会发现 user_list.jsondata 字段返回的是一个 User 类型的List,而 user_list2.jsondata 字段返回的是一个分页类型的Bean对象,这个Bean对象里的 datas 字段返回的是一个 User 类型的List;

(1)、方式一:使用泛型创建BaseResponse基类+data字段对应的序列化Bean对象:

首先序列化 data 字段对应的JSON数据:

dart 复制代码
// To parse this JSON data, do
//
//     final userPageBean = userPageBeanFromJson(jsonString);

import 'dart:convert';

import 'package:flutter3_wan_android/model/user.dart';

UserPageBean userPageBeanFromJson(String str) =>
    UserPageBean.fromJson(json.decode(str));

String userPageBeanToJson(UserPageBean data) => json.encode(data.toJson());

class UserPageBean {
  int curPage;
  List<User> datas;
  int offset;
  bool over;
  int pageCount;
  int size;
  int total;

  UserPageBean({
    required this.curPage,
    required this.datas,
    required this.offset,
    required this.over,
    required this.pageCount,
    required this.size,
    required this.total,
  });

  factory UserPageBean.fromJson(Map<String, dynamic> json) => UserPageBean(
        curPage: json["curPage"],
        datas: List<User>.from(json["datas"].map((x) => User.fromJson(x))),
        offset: json["offset"],
        over: json["over"],
        pageCount: json["pageCount"],
        size: json["size"],
        total: json["total"],
      );

  Map<String, dynamic> toJson() => {
        "curPage": curPage,
        "datas": List<dynamic>.from(datas.map((x) => x.toJson())),
        "offset": offset,
        "over": over,
        "pageCount": pageCount,
        "size": size,
        "total": total,
      };
}

解析数据:

dart 复制代码
Future decodeAssetJson() async {
	// 数据类型2-BaseResponse<T> + BaseList<T>  - 在分页相关接口,data 是一个对象
    // 解析方法1-生成data对应的Bean:user_page_bean.dart,然后结合base_response.dart
    // 解析本地数据-List数组
    Map<String, dynamic> json2Map =
        await loadJsonAssets("assets/user_list2.json");

	var json2Encode = jsonEncode(json2Map);

    BaseResponse<UserPageBean> userListMap3 =
        BaseResponse.fromJson(json2Map, (json) => UserPageBean.fromJson(json));

    var datas = userListMap3.data?.datas;

    if (kDebugMode) {
      print('\n =======================使用泛型解析开始========================== \n ');
      print('json2*  : $json2Map');
      print('json2Encode*  : $json2Encode');
      print('userListMap3*  : $userListMap3');
      print('userListMap3* toString : ${userListMap3.toString()}');
      print('userListMap3* message : ${userListMap3.message}');
      print('userListMap3* code : ${userListMap3.code}');
      print('userListMap3* data : ${userListMap3.data}');
      print('userListMap3* datas jsonEncode: ${jsonEncode(datas)}');

      print('\n ====================================================== \n ');
      print('usersMap2*  : $datas');
      print('usersMap2* toString : ${datas.toString()}');
      print('usersMap2* toList : ${datas?.toList()}');
    }

	if (kDebugMode) {
      print('\n =======================解析数组开始4========================== \n ');

      // jsonEncode转换字符串
      String userMapJson2 = jsonEncode(datas);

      // userMapJson jsonEncode:  [{"name":"Jerry","email":"Jerry@example.com"},{"name":"Alex","email":"Alex@example.com"},{"name":"Tom","email":"Tom@example.com"}]
      print('userMapJson2 jsonEncode:  $userMapJson2');

      // UserList-list :  [Instance of 'User', Instance of 'User', Instance of 'User']
      print('UserList-list :  $datas');
      // UserList-list toString:  [Instance of 'User', Instance of 'User', Instance of 'User']
      print('UserList-list toString:  ${datas.toString()}');

      if (datas != null && datas.isNotEmpty) {
        for (int i = 0; i < (datas.length); i++) {
          // UserList : => 0   Instance of 'User'
          print('UserList2  : => $i   ${datas[i].toString()}');
          // UserList toString : => 0   Instance of 'User'
          print('UserList2 toString : => $i   ${datas[i].toString()}');
          // UserList toJson : => 0   {name: Jerry, email: Jerry@example.com}
          print('UserList2 toJson : => $i   ${datas[i].toJson()}');
          // UserList jsonEncode : => 0   {"name":"Jerry","email":"Jerry@example.com"}
          print('UserList2 jsonEncode : => $i   ${jsonEncode(datas[i])}');
          // UserList name : => 0   Jerry
          print('UserList2 name : => $i   ${datas[i].name}');
          // UserList email : => 0   Jerry@example.com
          print('UserList2 email : => $i   ${datas[i].email}');
        }
      }
      print('\n =======================解析数组结束4========================== \n ');
      print('\n =======================使用泛型解析结束========================== \n ');
    }

}

输出日志:

dart 复制代码
json2*  : {data: {curPage: 1, datas: [{name: 肖战, email: 肖战@example.com}, {name: 丁程鑫, email: 丁程鑫@example.com}, {name: 贺峻霖, email: 贺峻霖@example.com}, {name: 李天泽, email: 李天泽@example.com}, {name: 刘耀文, email: 刘耀文@example.com}, {name: 成毅, email: 成毅@example.com}], offset: 0, over: false, pageCount: 3, size: 20, total: 46}, code: 0, message: Success get}
json2Encode*  : {"data":{"curPage":1,"datas":[{"name":"肖战","email":"肖战@example.com"},{"name":"丁程鑫","email":"丁程鑫@example.com"},{"name":"贺峻霖","email":"贺峻霖@example.com"},{"name":"李天泽","email":"李天泽@example.com"},{"name":"刘耀文","email":"刘耀文@example.com"},{"name":"成毅","email":"成毅@example.com"}],"offset":0,"over":false,"pageCount":3,"size":20,"total":46},"code":0,"message":"Success get"}
userListMap3*  : Instance of 'BaseResponse<UserPageBean>'
userListMap3* toString : Instance of 'BaseResponse<UserPageBean>'
userListMap3* message : Success get
userListMap3* code : 0
userListMap3* data : Instance of 'UserPageBean'
userListMap3* datas jsonEncode: [{"name":"肖战","email":"肖战@example.com"},{"name":"丁程鑫","email":"丁程鑫@example.com"},{"name":"贺峻霖","email":"贺峻霖@example.com"},{"name":"李天泽","email":"李天泽@example.com"},{"name":"刘耀文","email":"刘耀文@example.com"},{"name":"成毅","email":"成毅@example.com"}]
====================================================== 
usersMap2*  : [Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User']
usersMap2* toString : [Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User']
usersMap2* toList : [Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User']
=======================解析数组开始4========================== 
userMapJson2 jsonEncode:  [{"name":"肖战","email":"肖战@example.com"},{"name":"丁程鑫","email":"丁程鑫@example.com"},{"name":"贺峻霖","email":"贺峻霖@example.com"},{"name":"李天泽","email":"李天泽@example.com"},{"name":"刘耀文","email":"刘耀文@example.com"},{"name":"成毅","email":"成毅@example.com"}]
UserList-list :  [Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User']
UserList-list toString:  [Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User']
UserList2  : => 0   Instance of 'User'
UserList2 toString : => 0   Instance of 'User'
UserList2 toJson : => 0   {name: 肖战, email: 肖战@example.com}
UserList2 jsonEncode : => 0   {"name":"肖战","email":"肖战@example.com"}
UserList2 name : => 0   肖战
UserList2 email : => 0   肖战@example.com

...

使用 BaseResponse 包装 UserPageBean 对象,然后对其进行解析,获取对应的 datas 数组列表,接下来就是常规的数据解析了。

核心代码:

dart 复制代码
BaseResponse<UserPageBean> userListMap3 =
        BaseResponse.fromJson(json2Map, (json) => UserPageBean.fromJson(json));

var datas = userListMap3.data?.datas;

(2)、方式二:使用泛型创建BaseResponse基类+data字段对应的序列化泛型类对象BaseList:

封装一个 BaseList 对象,序列化代码:

dart 复制代码
/// 一个注释,用于代码生成器,使其知道该类需要生成JSON序列化逻辑
@JsonSerializable(genericArgumentFactories: true)
class BaseList<T> {
  List<T> datas;

  BaseList(this.datas);

  factory BaseList.fromJson(
    Map<String, dynamic> json,
    T Function(dynamic json) fromJsonT,
  ) =>
      _$BaseListFromJson<T>(json, fromJsonT);

  Map<String, dynamic> toJson(Object? Function(T value) toJsonT) =>
      _$BaseListToJson<T>(this, toJsonT);
}

数据解析:

dart 复制代码
Future decodeAssetJson() async {
    BaseResponse<BaseList<User>> userListMap3 = BaseResponse.fromJson(json2Map,
        (json) => BaseList.fromJson(json, (json) => User.fromJson(json)));

	BaseList<User>? baseUsers = userListMap3.data;
	// var datas = baseUsers?.datas;
	List<User>? usersMap3 = baseUsers?.datas;
	if (kDebugMode) {
      print('\n =======================使用泛型解析开始========================== \n ');

      print('\n ====================================================== \n ');
      print('userListMap3*  : $userListMap3');
      print('userListMap3* message : ${userListMap3.message}');
      print('userListMap3* code : ${userListMap3.code}');
      print('userListMap3* data : ${userListMap3.data}');
      print('userListMap3* toString : ${userListMap3.toString()}');

      print('\n ====================================================== \n ');
      print('baseUsers*  : $baseUsers');
      print('baseUsers* datas : ${baseUsers?.datas}');

      print('\n ====================================================== \n ');
      print('usersMap3*  : $usersMap3');
      print('usersMap3* toString : ${usersMap3.toString()}');
      print('usersMap3* toList : ${usersMap3?.toList()}');
    }
    if (kDebugMode) {
      print('\n =======================解析数组开始5========================== \n ');

      // jsonEncode转换字符串
      String userMapJson3 = jsonEncode(usersMap3);

      // userMapJson jsonEncode:  [{"name":"Jerry","email":"Jerry@example.com"},{"name":"Alex","email":"Alex@example.com"},{"name":"Tom","email":"Tom@example.com"}]
      print('userMapJson3 jsonEncode:  $userMapJson3');

      // UserList-list :  [Instance of 'User', Instance of 'User', Instance of 'User']
      print('UserList-list :  $usersMap3');
      // UserList-list toString:  [Instance of 'User', Instance of 'User', Instance of 'User']
      print('UserList-list toString:  ${usersMap3.toString()}');

      if (usersMap3 != null && usersMap3.isNotEmpty) {
        for (int i = 0; i < (usersMap3.length); i++) {
          // UserList : => 0   Instance of 'User'
          print('UserList3  : => $i   ${usersMap3[i].toString()}');
          // UserList toString : => 0   Instance of 'User'
          print('UserList3 toString : => $i   ${usersMap3[i].toString()}');
          // UserList toJson : => 0   {name: Jerry, email: Jerry@example.com}
          print('UserList3 toJson : => $i   ${usersMap3[i].toJson()}');
          // UserList jsonEncode : => 0   {"name":"Jerry","email":"Jerry@example.com"}
          print('UserList3 jsonEncode : => $i   ${jsonEncode(usersMap3[i])}');
          // UserList name : => 0   Jerry
          print('UserList3 name : => $i   ${usersMap3[i].name}');
          // UserList email : => 0   Jerry@example.com
          print('UserList3 email : => $i   ${usersMap3[i].email}');
        }
      }
      print('\n =======================解析数组结束5========================== \n ');
      print('\n =======================使用泛型解析结束========================== \n ');
    }
}

输出日志:

dart 复制代码
userListMap3*  : Instance of 'BaseResponse<BaseList<User>>'
userListMap3* toString : Instance of 'BaseResponse<BaseList<User>>'
userListMap3* message : Success get
userListMap3* code : 0
userListMap3* data : Instance of 'BaseList<User>'
baseUsers*  : Instance of 'BaseList<User>'
baseUsers* datas : [Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User']
====================================================== 
usersMap3*  : [Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User']
usersMap3* toString : [Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User']
usersMap3* toList : [Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User']
=======================解析数组开始5========================== 
 userMapJson3 jsonEncode:  [{"name":"肖战","email":"肖战@example.com"},{"name":"丁程鑫","email":"丁程鑫@example.com"},{"name":"贺峻霖","email":"贺峻霖@example.com"},{"name":"李天泽","email":"李天泽@example.com"},{"name":"刘耀文","email":"刘耀文@example.com"},{"name":"成毅","email":"成毅@example.com"}]
UserList-list :  [Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User']
UserList-list toString:  [Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User', Instance of 'User']
UserList3  : => 0   Instance of 'User'
UserList3 toString : => 0   Instance of 'User'
UserList3 toJson : => 0   {name: 肖战, email: 肖战@example.com}
UserList3 jsonEncode : => 0   {"name":"肖战","email":"肖战@example.com"}
UserList3 name : => 0   肖战
UserList3 email : => 0   肖战@example.com

...

使用 BaseResponse 包装 BaseList<T> 对象,BaseList<T> 包装 User, 然后对其进行解析,获取对应的 datas 数组列表,接下来就是常规的数据解析了。

核心代码:

dart 复制代码
BaseResponse<BaseList<User>> userListMap3 = BaseResponse.fromJson(json2Map,
        (json) => BaseList.fromJson(json, (json) => User.fromJson(json)));

BaseList<User>? baseUsers = userListMap3.data;
// var datas = baseUsers?.datas;
List<User>? usersMap3 = baseUsers?.datas;

对比:

方式一和方式二没有多大的区别,方式一是将所有的返回数据序列化,而方式二则是封装 BaseList<T> 使用泛型包装具体的Bean对象;但是对比数据解析的代码,好像方式一的更加简洁一点;


总结

本文记录了解析序列化复杂JSON数据的几个方法,又区分了直接返回数组列表格式的JOSN数据和返回分页数组列表的JSON数据,以及它们各自的多个不同解析方式,大同小异;下一节,介绍下同意封装的Base基类,区分这两种返回格式;个人觉得直接使用序列化相同部分即可,比如2-1(方式一:使用泛型创建BaseResponse基类+data字段对应的序列化Bean对象);

相关推荐
一个处女座的程序猿O(∩_∩)O2 小时前
小型 Vue 项目,该不该用 Pinia 、Vuex呢?
前端·javascript·vue.js
hackeroink5 小时前
【2024版】最新推荐好用的XSS漏洞扫描利用工具_xss扫描工具
前端·xss
迷雾漫步者6 小时前
Flutter组件————FloatingActionButton
前端·flutter·dart
向前看-7 小时前
验证码机制
前端·后端
燃先生._.8 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
高山我梦口香糖9 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
m0_748235249 小时前
前端实现获取后端返回的文件流并下载
前端·状态模式
m0_7482402510 小时前
前端如何检测用户登录状态是否过期
前端
black^sugar10 小时前
纯前端实现更新检测
开发语言·前端·javascript