草庐IT

Flutter解析Json最好用的工具

差点长成一枚帅哥 2023-03-28 原文

相信做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,当时搞的我都飘了。

有关Flutter解析Json最好用的工具的更多相关文章

  1. Ruby 解析字符串 - 2

    我有一个字符串input="maybe(thisis|thatwas)some((nice|ugly)(day|night)|(strange(weather|time)))"Ruby中解析该字符串的最佳方法是什么?我的意思是脚本应该能够像这样构建句子:maybethisissomeuglynightmaybethatwassomenicenightmaybethiswassomestrangetime等等,你明白了......我应该一个字符一个字符地读取字符串并构建一个带有堆栈的状态机来存储括号值以供以后计算,还是有更好的方法?也许为此目的准备了一个开箱即用的库?

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby - 用逗号、双引号和编码解析 csv - 2

    我正在使用ruby​​1.9解析以下带有MacRoman字符的csv文件#encoding:ISO-8859-1#csv_parse.csvName,main-dialogue"Marceu","Giveittohimóhe,hiswife."我做了以下解析。require'csv'input_string=File.read("../csv_parse.rb").force_encoding("ISO-8859-1").encode("UTF-8")#=>"Name,main-dialogue\r\n\"Marceu\",\"Giveittohim\x97he,hiswife.\"\

  4. ruby-on-rails - Rails HTML 请求渲染 JSON - 2

    在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这

  5. ruby-on-rails - 我更新了 ruby​​ gems,现在到处都收到解析树错误和弃用警告! - 2

    简而言之错误:NOTE:Gem::SourceIndex#add_specisdeprecated,useSpecification.add_spec.Itwillberemovedonorafter2011-11-01.Gem::SourceIndex#add_speccalledfrom/opt/local/lib/ruby/site_ruby/1.8/rubygems/source_index.rb:91./opt/local/lib/ruby/gems/1.8/gems/rails-2.3.8/lib/rails/gem_dependency.rb:275:in`==':und

  6. ruby-on-rails - 如何使用 Rack 接收 JSON 对象 - 2

    我有一个非常简单的RubyRack服务器,例如:app=Proc.newdo|env|req=Rack::Request.new(env).paramspreq.inspect[200,{'Content-Type'=>'text/plain'},['Somebody']]endRack::Handler::Thin.run(app,:Port=>4001,:threaded=>true)每当我使用JSON对象向服务器发送POSTHTTP请求时:{"session":{"accountId":String,"callId":String,"from":Object,"headers":

  7. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  8. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  9. postman接口测试工具-基础使用教程 - 2

    1.postman介绍Postman一款非常流行的API调试工具。其实,开发人员用的更多。因为测试人员做接口测试会有更多选择,例如Jmeter、soapUI等。不过,对于开发过程中去调试接口,Postman确实足够的简单方便,而且功能强大。2.下载安装官网地址:https://www.postman.com/下载完成后双击安装吧,安装过程极其简单,无需任何操作3.使用教程这里以百度为例,工具使用简单,填写URL地址即可发送请求,在下方查看响应结果和响应状态码常用方法都有支持请求方法:getpostputdeleteGet、Post、Put与Delete的作用get:请求方法一般是用于数据查询,

  10. ruby - 用 YAML.load 解析 json 安全吗? - 2

    我正在使用ruby2.1.0我有一个json文件。例如:test.json{"item":[{"apple":1},{"banana":2}]}用YAML.load加载这个文件安全吗?YAML.load(File.read('test.json'))我正在尝试加载一个json或yaml格式的文件。 最佳答案 YAML可以加载JSONYAML.load('{"something":"test","other":4}')=>{"something"=>"test","other"=>4}JSON将无法加载YAML。JSON.load("

随机推荐