JSON是移动端开发常用的应用层数据交换协议。最常见的场景便是,客户端向服务端发起网络请求,服务端返回JSON文本,然后客户端解析这个JSON文本,再把对应数据展现到页面上。
但在编程的时候,处理JSON是一件麻烦事。在不引入任何轮子的情况下,我们通常需要先把JSON转为Dictionary,然后还要记住每个数据对应的Key,用这个Key在Dictionary中取出对应的Value来使用。这个过程我们会犯各种错误:

* Key拼写错了
* 路径写错了
* 类型搞错了
* 没拿到值懵逼了
* 某一天和服务端约定的某个字段变更了,没能更新所有用到它的地方
* ...

为了解决这些问题,很多处理JSON的开源库应运而生。在Swift中,这些开源库主要朝着两个方向努力:

1. 保持JSON语义,直接解析JSON,但通过封装使调用方式更优雅、更安全
2. 预定义Model类,将JSON反序列化为类实例,再使用这些实例

对于1,使用最广、评价最好的库非 SwiftyJSON 莫属,它很能代表这个方向的核心。它本质上仍然是根据JSON结构去取值,使用起来顺手、清晰。但也正因如此,这种做法没能妥善解决上述的几个问题,因为Key、路径、类型仍然需要开发者去指定;

对于2,我个人觉得这是更合理的方式。由于Model类的存在,JSON的解析和使用都受到了定义的约束,只要客户端和服务端约定好了这个Model类,客户端定义后,在业务中使用数据时就可以享受到语法检查、属性预览、属性补全等好处,而且一旦数据定义变更,编译器会强制所有用到的地方都改过来才能编译通过,非常安全。这个方向上,开源库们做的工作,主要就是把JSON文本反序列化到Model类上了。这一类JSON库有 ObjectMapper、JSONNeverDie、HandyJSON 等。

今天我们先来看看SwiftyJSON的用法。

通常我们拿到数据会进行非常麻烦的optinonal(可选类型)进行拆包(Wrapping )操作,
SwiftyJson内部会自动对optional进行拆包,大大简化了代码,解析非常方便,拿到的json数据data直接扔进去

​​​​​​​

//转成JSON对象
let jsonData = JSON.init(data)

不管需要什么数据只要通过对jsonData进行路径读取
例如:

let build_name = jsonData[0]["build_name"].stringValue

值得一提的是,不需要考虑服务器给我们返回的是什么类型,比如去请求一个房屋的栋数"build_num": 588我们想要获得Int类型或者String类型都可以

let room_num1 = jsonData[0]["build_num"].stringValue
let room_num2 = jsonData[0]["build_num"].intValue
// room_num1 = 588   String类型
// room_num2 = 588   Int类型这样通过.stringValue.intValue就可以获得不可选值类型,如果没有获取到数据的话就会返回一个默认值即.stringValue获得空字符串"".intValue得到0.arrayValue获得空数组[],我们就不用判断拆包了。

当然某些场景可能需要你得到可选值类型并自己判断是否存在,那么我们可以通过.string .int .bool .float .array .dictionary等等方法获取,例如:

​​​​​​​

//String
if let build_name = jsonData[0]["build_name"].string {
    print(build_name)
} else {
    //打印错误信息
    print(jsonData[0]["build_name"])
}

解析数据是真的非常简单。详细使用可以看看SwiftyJSON的使用详解(附样例)
或者移步GitHub-SwiftyJson
但是对于项目而言我们需要对数据进行转换为模型,仅仅是对data进行JSON读取是远远不够的,想想,如果遇到许多地方都用到了build_name值,但是当服务器给我们返回的字段名字改了,我们改项目时就会显得麻烦,甚至造成改不完全,所以我们队数据封装一下转为模型,这样修改时只用改一个地方就是model的赋值就好了。

那我的方法是:

​​​​​​​

//这是模拟数据
let baseInfo: [String : Any] = ["build_name":"置信·原墅",
                                  "build_address":"学院中路与金桥路交汇处东北侧",
                                  "build_num": 12,
                                  "room_num": 588,
                                  "area_address":"浙江省温州市鹿城区五马街道"]

创建struct模型,当然Class也可以,但是如果不需要继承也不复杂推荐struct(-。-不多解释了)
并写好创建方法

​​​​​​​

import SwiftyJSON
 
struct BuildBaseInfoModel {
    var build_name: String?
    var build_address: String?
    var build_num: String?
    var room_num: String?
    var area_address: String?
    
    init(jsonData: JSON) {
        build_name    = jsonData["build_name"].stringValue
        build_address = jsonData["build_address"].stringValue
        area_address  = jsonData["area_address"].stringValue
        room_num      = jsonData["room_num"].stringValue
        build_num     = jsonData["build_num"].stringValue
    }
}

调用:

​​​​​​​

let jsonData = JSON(baseInfo)
let model = BuildBaseInfoModel.init(jsonData: jsonData)
// 会得到创建好的 BuildBaseInfoModel类型的 对象model
// 也可以这样写
let model = BuildBaseInfoModel(jsonData: jsonData)

当然这只是普通的模型,经常会遇到复杂模型,例如:

​​​​​​​

// 面积中89是Int, 109和129是String
let baseInfo: [String : Any] = ["build_name":"置信·原墅",
                                  "build_address":"学院中路与金桥路交汇处东北侧",
                                  "area_address":"浙江省温州市鹿城区五马街道",
                                  "area":[89,"109","129"],
                                  "detail_address":["province":"浙江省",
                                                    "city":"温州市",
                                                    "district":"鹿城区",
                                                    "street":"五马街道"],
                                  "build_num": 12,
                                  "room_num": 588]

这时候模型就应该有两个

​​​​​​​

struct BuildBaseInfoModel {
    
    var build_name: String?
    var build_address: String?
    var build_num: String?
    var room_num: String?
    var area_address: String?
    var detail_address: DetailAddressModel
    var area:[Any]?
    // 这里面积area中就不能再用arrayValue获取了,因为arrayValue获取的为JSON类型,我们需要转为我们需要的对象
    init(jsonData: JSON) {
        build_name    = jsonData["build_name"].stringValue
        build_address = jsonData["build_address"].stringValue
        area_address  = jsonData["area_address"].stringValue
        room_num      = jsonData["room_num"].stringValue
        build_num     = jsonData["build_num"].stringValue
        area          = jsonData["area"].arrayObject
        detail_address = DetailAddressModel(jsonData: jsonData["detail_address"])
    }
}
struct DetailAddressModel {
    var province: String?
    var city: String?
    var district: String?
    var street: String?
    
    init(jsonData: JSON) {
        province = jsonData["province"].stringValue
        city = jsonData["city"].stringValue
        district = jsonData["district"].stringValue
        street = jsonData["street"].stringValue
    }
    
}

​​​​​​​​​​​​​​let model = BuildBaseInfoModel(jsonData: jsonData)
DPrint(message: model.detail_address.city)
DPrint(message: model.area?.first)
DPrint(message: model.area?[1])
// xxxxxxxxx.swift[21], updateRoomsData(index:): Optional("温州市")
// xxxxxxxxx.swift[22], updateRoomsData(index:): Optional(89)
// xxxxxxxxx.swift[22], updateRoomsData(index:): Optional("109")

SwiftyJSON 对网络请求来的数据进行解析或者转为modul相关推荐

  1. 微信小程序教学第二章(含视频):小程序中级实战教程之预备篇 - 封装网络请求及 mock 数据...

    § 封装网络请求及 mock 数据 本文配套视频地址: v.qq.com/x/page/i055- 开始前请把 ch2-3 分支中的 code/ 目录导入微信开发工具 上一节中,我们对 index.j ...

  2. 【苹果相册推送】软件安装表现到ListView中,把网络请求来的数据存储下来

    推荐内容IMESSGAE相关 作者推荐内容 iMessage苹果推软件 *** 点击即可查看作者要求内容信息 作者推荐内容 1.家庭推内容 *** 点击即可查看作者要求内容信息 作者推荐内容 2.相册 ...

  3. ios获取网络请求失败相关数据

    ios获取网络请求失败相关数据 很多时候和后台处理数据的时候很多时候后台会在网络请求失败的某些不同情况下带回不同的数据这个时候如何获取数据及拿到需要处理的数据: //如果请求失败 对象是NSURLSe ...

  4. 「Python 编程」编码实现网络请求库中的 URL 解析器

    相信各位 Python 开发者都用过 Requests 库,有些朋友还用过 WebSockets 库.这里回顾一下它们的基本用法,例如使用 Requests 库向目标网站发出 GET 请求: impo ...

  5. C#获取http请求的JSON数据并解析

    文章目录 1️⃣ C#获取http请求的JSON数据并解析 1.1 获取http的JSON数据 1.2 解析JSON数据 优质资源分享 C#获取http请求的JSON数据并解析,第一步,先拿到http ...

  6. 二、Swift网络请求回来的数据我这样取

    网络请求框架Alamofire 源码地址 Swift 2.3 Alamofire3.0版本支持 iOS 8 Swift 3 Alamofire4.0以上版本支持 iOS 9及以上系统 json数据: ...

  7. (原创)使用AsyncTask(带修改线程池方式)+自定义ImageLoader+LRU算法对图片三级缓存及其显示优化(只有在ListView滑动停止的时候才去网络请求获取图片数据)

    前言: 以前看了些关于图片优化处理缓存比较全的视频(感谢慕风网),现在回顾觉得还是挺好的也就总结出来下,感觉针对图片做处理这块还真的用的比较多,本文章只要使用异步线程AsyncTask.自定义的Ima ...

  8. JS 借助 pako.js 实现网络请求获取 gzip 数据流并解析, 解决汉字乱码

    1, 下载 pako.js => http://nodeca.github.io/pako/#Deflate.prototype.onData 2, 首先需要了解一下 XMLHttpReques ...

  9. 用Alamofire进行网络请求的一段代码解析(一)

    //AnyObject:json //Mark:利用alamofire 发送网络请求,并返回数据json:AnyObject,需要强制转换为NSDictionary字典类型. /* 向服务器发送请求: ...

  10. 网络请求可以返回数据的网站_实例解析|Python加解密VIP网站反爬请求头实现数据爬取...

    原文作者:州的先生原文地址:https://zmister.com/archives/812.html 在正常情况下,对于需要登录的网站,一般只要将登录后的cookie携带到headers中就可以实现 ...

最新文章

  1. 一个生成全局唯一Sequence ID的高并发工厂类 (Java)
  2. 周五晚上看了变形金刚
  3. ios无痕埋点_iOS可视化埋点方案
  4. ppp chap 加密摘要_“网络工程师培训”基础教程:一文读懂PPP协议
  5. 幼师学计算机心得体会怎么写,幼儿教师学习心得
  6. 为什么都建议学java而不是python-现在学Python还是Java好呢?
  7. AutoCad二次开发-插入DWG参照 Teigha库
  8. 做H5页面用什么软件比较好?3款易上手好用的H5网页编辑工具
  9. 御用导航提示提醒_AR实景导航,让你安全驾驶,不再“绕弯”
  10. ocf heartbeat mysql_Heartbeat CRM模式
  11. word转chm文件
  12. 微信小游戏排行榜制作(主域子域)
  13. SpringBoot + uni-app开发企业级图书商城系统
  14. 掘金茅台,三位投资客的暴富人生
  15. Vue中图片实现毛玻璃效果
  16. Java中同包和不同包类进行相互访问的问题
  17. BreederDAO 宣布与 20 多个区块链游戏建立官方合作关系
  18. 【QT Creator学习记录】(一)上位机与下位机串口通信
  19. hive的列分隔符和行分隔符的使用
  20. nacos 单机部署_使用Docker部署Nacos-Server(单机版)

热门文章

  1. 2021-08-08 解决“These dependencies were not found“的报错
  2. 谷歌翻译配置hosts
  3. java.lang.IllegalStateException: Max number of active transactions reached:50
  4. nlp 停用词处理java_NLP入门:文本预处理(一)停用词
  5. “跟着吴恩达老师入门机器学习”学习笔记(二)
  6. 开源BT磁力搜索引擎收集
  7. 日本酒店寄送行李至机场的攻略
  8. 线程安全的几种单例模式
  9. java求职简历模板自我评价_java简历自我评价填写样本
  10. 【正点原子STM32连载】第十章 STM32CubeMX简介 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1