Flutter解析Json最好用的工具

相信做Flutter开发的小伙伴们曾经都有这样的痛苦,接口明明是联调OK的,怎么提测以后接口就出问题了,有一种情况是这样的,后台哥们很不负责任的调整了字段类型,或者修改了字段名,再或者缺少了原有返回的字段。

首先看下,相信大家正常都是这样解析json的

//假如已经获取到了从后台的response
Map<String, dynamic> json =  [];

//解析String值与int值
String nickname = json["nickname"];
int userId = json["userId"];

这种写法,如果后台没有返回nickname字段,或者userId后台返回的是字符串类型,这里json解析就会报错,flutter不像原生解析一样有json.optString或者json.optInt这样的方法,当然在fluttermap也有containsKey方法,判断该字段是否存在,难道.....我要对每个字段进行判断吗?如果非要我这样做,我会把后台杀了。

有没有什么方法可以像原生Android一样解析,直接json.optString()一样处理,及时后台没有返回该字段,或者数据类型对不上,app这边依然可以正常运行,不会程序报错,答案是有的,那就是extension method处理,实现map的扩展函数(getString,getInt,getBool)这样的方法,然后在里面自己进行容错处理即可)java是不能实现扩展函数的,kotlinflutter却可以,废话不多说,直接上代码吧。

/**
 * 扩展工具类
 */
extension ExtensionUtils on Map {

  /**
   * 返回一个int值
   */
  int getInt(String key, {int defValue = 0}) {
    try {
      if (containsKey(key)) {
        var value = this[key];
        if (null == value) {
          return defValue;
        } else if (value is String) {
          return int.parse(value);
        }
        return value;
      }
    } on Exception {
    } catch (e) {}
    return defValue;
  }

  /**
   * 返回一个String值
   */
  String getString(String key, {String defValue = ""}) {
    try {
      if (containsKey(key)) {
        var value = this[key];
        if (null == value) {
          return defValue;
        } else if (value is int) {
          return value.toString();
        }
        return this[key];
      }
    } on Exception {
    } catch (e) {}
    return defValue;
  }

  /**
   * 返回一个map
   */
  Map<String, dynamic> getMap(String key) {
    try {
      if (containsKey(key)) {
        return this[key];
      }
    } on Exception {
    } catch (e) {}
    return {};
  }

  /**
   * 返回一个对象
   */
  T getObject<T>(String key, T Function(Map<String, dynamic>) parseModel) {
    try {
      if (this.containsKey(key) && null != this[key]) {
        return parseModel(this[key]);
      } else {
        return parseModel({});
      }
    } on Exception {
      return parseModel({});
    }
  }

  /**
   * 解析list
   */
  List<T> getList<T>(String key, T Function(dynamic data) parseModel) {
    try {
      List list = this[key] ?? [];
      List<T> datas = list.map((e) => parseModel(e)).toList();
      return datas;
    } on Exception {
      return [];
    }
  }
}

最后看下我是如何调用的
解析int,String

import 'package:app_flutter/utils/extensions_utils.dart';
class Shift {
  String? endTime;
  int? groupId;
  String? workStatus; //WORKING:值班中, RESTING:休息中,HANDOVER_WORK: 交班, RECEIVING_WORK: 接班
  String? workStatusDesc;

  Shift.fromJson(Map<String, dynamic> json) {
    endTime = json.getString("endTime");
    groupId = json.getInt("groupId");
    workStatus = json.getString("workStatus");
    workStatusDesc = json.getString("workStatusDesc");
  }
}

解析object对象与解析list数组

import 'package:app_flutter/utils/extensions_utils.dart';

import 'message_ext.dart';

/**
 * 未读消息体
 */
class MessageNotify {

  late String content;//    内容  string
  late MessageExt ext;//    扩展数据    object
  late String id;// id  string
  late int isRead;//    是否已读(0:否,1:是)   integer
  late String msgId;//  消息id    integer
  late String recId;//  接收者id   string
  late List<String> tags;// 标签数组    array   string
  late String time;//   时间  string
  late String title;//  标题

  MessageNotify.from(Map<String, dynamic> map){
    content = map.getString("content");
    ext = map.getObject("ext", (data){ return MessageExt.from(data);});
    id = map.getString("id");
    isRead = map.getInt("isRead");
    msgId = map.getString("msgId");
    recId = map.getString("recId");
    tags = map.getList("tags", (item){return item.toString();});
    time = map.getString("time");
    title = map.getString("title");
  }
}

补充下MessageExt.dart

import 'package:app_flutter/constant/asset_path_constant.dart';
import 'package:app_flutter/utils/extensions_utils.dart';

/**
 * 未读消息-扩展字段
 */
class MessageExt {
  late int msgType; //: 0事件,1待办,2逾期,3临期
  late String typeId; //: 事件ID或工单ID
  late String businessId;// 业务ID,当type为 3,4的时候,该字段有值
  late int type; //: 0告警事件,1报修事件,2告警工单,3保养工单,4巡检工单,5维修工单
  late String msgTip; //:严重,巡检,维保,告警处置
  late String msgIcon; //: 图标路径

  MessageExt.from(Map<String, dynamic> map) {
    msgType = map.getInt("msgType");
    typeId = map.getString("typeId");
    type = map.getInt("type");
    msgTip = map.getString("msgTip");
    msgIcon = map.getString("msgIcon");
    businessId = map.getString("businessId");
  }
}

此工具类一出,方便了组内的其他小伙伴,老大直接给我call了波666,当时搞的我都飘了。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,458评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,454评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,171评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,062评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,440评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,661评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,906评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,609评论 0 200
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,379评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,600评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,085评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,409评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,072评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,088评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,860评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,704评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,608评论 2 270

推荐阅读更多精彩内容