ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Flutter JSON 解析

2021-01-25 16:33:22  阅读:200  来源: 互联网

标签:Map resp registered json dart JSON build 解析 Flutter


原理

因为 tree shaking,Flutter 禁用了 Dart 的反射,Flutter 禁用了 Dart 的反射,Flutter 禁用了 Dart 的反射,重要的事情说三遍,所以 Flutter 无法用 JSON decode 泛型 model,解决方法是使用 json_serializable 把响应基类先 decode,并把响应数据类型 decode 为 Map<String, dynamic>,在需要使用响应数据类型的地方再调用实际类型的 fromJson 序列化。

REST 接口

REST 接口请求参数样例为,请求方式为 POST Request Body:{"countryCode": "86", "telNo": "13227753101"}
REST 接口响应参数样例为:{"code": 0, "msg": "ok", "data": {"registered": true}}

Flutter 解析

依赖 pubspec.yaml

...
dependencies:
  ...
  http: ^0.12.2
  json_annotation: ^3.1.1

dev_dependencies:
  ...
  build_runner: ^1.11.0
  json_serializable: ^3.5.1
...

编译前置脚本 build.sh

#!/bin/bash

############################################################################
## 项目编译前置脚本
## 使用:chmod +x build.sh && ./build.sh
############################################################################

echo 'Start build music_hub_frontend'

# 拉取依赖
flutter pub get

# 生成 model 类
cd lib/model/
flutter packages pub run build_runner build
cd -

echo 'Build success'

所有 model 类均放置在 lib/model 下。

响应基类 lib/model/resp.dart

import 'package:json_annotation/json_annotation.dart';

part 'resp.g.dart';

/// 接口响应模型基类
/// json_serializable 不支持泛型
/// 所以只能把实际数据丢成 Map<String, dynamic> 在实际使用的地方再解析一遍
///
/// @author seliote
/// @since 2021-01-25
@JsonSerializable()
class Resp {
  // 请求响应状态码,不可为 null
  @JsonKey(name: "code")
  int code;

  // 请求响应状态码描述,不可为 null
  @JsonKey(name: "msg")
  String msg;

  // 请求响应实际数据,可能为 null
  @JsonKey(name: "data")
  Map<String, dynamic> data;

  Resp(this.code, this.msg, this.data);

  factory Resp.fromJson(Map<String, dynamic> json) => _$RespFromJson(json);

  Map<String, dynamic> toJson() => _$RespToJson(this);

  /// 判断响应对应的操作是否成功
  bool isSuccess() {
    return code == 0;
  }

  /// 请求结果展示信息
  String displayMsg() {
    // 没用国际化
    switch (code) {
      case 0:
        return "成功";
      case -1000:
        return "未知异常";
      case -1001:
        return "请求地址异常";
      case -1002:
        return "请求参数异常";
      default:
        return "信息未配置";
    }
  }
}

响应数据类型 lib/model/user/registered_status.dart

import 'dart:core';

import 'package:json_annotation/json_annotation.dart';

part 'registered_status.g.dart';

/// /user/registered_status 实体类
///
/// @author seliote
/// @since 2021-01-23

/// /user/registered_status 请求实体类
@JsonSerializable()
class RegisteredStatusReq {
  @JsonKey(name: "country_code")
  String countryCode;

  @JsonKey(name: "tel_no")
  String telNo;

  RegisteredStatusReq(this.countryCode, this.telNo);

  factory RegisteredStatusReq.fromJson(Map<String, dynamic> json) =>
      _$RegisteredStatusReqFromJson(json);

  Map<String, dynamic> toJson() => _$RegisteredStatusReqToJson(this);
}

/// /user/registered_status 响应实体类
@JsonSerializable()
class RegisteredStatusResp {
  @JsonKey(name: "registered")
  bool registered;

  RegisteredStatusResp(this.registered);

  factory RegisteredStatusResp.fromJson(Map<String, dynamic> json) =>
      _$RegisteredStatusRespFromJson(json);

  Map<String, dynamic> toJson() => _$RegisteredStatusRespToJson(this);
}

项目根目录下执行编译前置脚本:chmod +x build.sh && ./build.sh,此时 JSON 解析格式已经完成,接下来是使用部分。

HTTP 请求封装 lib/util/backend_utils.dart

import 'dart:convert';

import 'package:frontend/model/resp.dart';
import 'package:http/http.dart' as http;

/// 后台相关工具
///
/// @author seliote
/// @since 2021-01-23

const String SCHEME = "http";
// 服务器应用部署 URL
const String SERVER_URL = "localhost";
// 服务器端口
const int SERVER_PORT = 80;

/// Post 方式发送 request body
Future<Resp> post<T>(String path, Object reqBody) async {
  Map<String, String> headers = {"Content-Type": "application/json"};
  var url = "$SCHEME://$SERVER_URL:$SERVER_PORT$path";
  var resp = await http.post(url, headers: headers, body: json.encode(reqBody));
  var respModel = Resp.fromJson(json.decode(resp.body));
  return respModel;
}

实际请求代码:

...
    var next = FlatButton(
        onPressed: () async {
          var resp = await post<RegisteredStatusResp>(
              "/user/registered_status",
              RegisteredStatusReq(
                  countryCode.data, textEditingController.text));
          if (resp.isSuccess()) {
            print(RegisteredStatusResp.fromJson(resp.data).toJson());
          } else {
            print(resp.displayMsg());
          }
        },
...

标签:Map,resp,registered,json,dart,JSON,build,解析,Flutter
来源: https://www.cnblogs.com/seliote/p/14325887.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有