Swift json字典转模型 项目记录
背景
最近项目开始转用Swift3开发,由于Swift中json(字典)转模型的选择方案较多,笔者最开始选择了HandyJSON的方案,在使用一段时间后发现当要进行某个字段取值使用时需要进行各种的转化判断,比较麻烦(但是安全、保证程序不会抛出异常)。于是笔者引入了SwiftyJSON库。于是取值变得简单方便。
新问题
由于SwiftyJSON的引入,笔者将网络请求基本请求完成后进行了JSON化处理,如果后面再进行HandyJSON转模型处理,就要进行二次操作,感觉效率上会有影响。
当然也可以选择网络请求基类对返回数据不做任何处理,交还由各个请求发起者处理,但这样会导致大量的重复代码。在这种情况下笔者思考利用JSON自己进行模型转化。
方案
runtime机制给模型赋值
在OC中我们的json转模型通常是利用runtime机制获取模型对象的属性列表,再进行判断并取值赋值.由于Swift中已经逐渐放弃runtime机制。因此笔者放弃了此种方案
反射机制给模型赋值
在Swift中有一个Mirror类,具备获取对象信息能力、能获取对象名字及值。接着再通过kvc的方式将值写入模型即可。(HandyJSON的值写入是直接通过内存地址写入)
实现
这里笔者通过反射机制来实现json转模型(由于项目中使用到了SwiftyJSON,因此添加了JOSN转化为模型方法)。模型基类代码如下
import UIKit
import SwiftyJSON
class BQModel: NSObject {
required override init() {
}
required init(_ dic: Dictionary<String,Any>) {
super.init()
self.configValue(dic)
}
func configValue(_ dic: Dictionary<String,Any>) {
let mirror = Mirror(reflecting: self)
for p in mirror.children {
let name = p.label!
if let value = dic[name] {
if p.value is BQModel && value is Dictionary<String, Any> {
(p.value as! BQModel).configValue(value as! Dictionary<String, Any>)
}else {
self.setValue(value, forKey: name)
}
}
}
}
override var description: String {
let mirror = Mirror(reflecting: self)
var result = [String:Any]()
for p in mirror.children {
let name = p.label!
result[name] = p.value
}
return String(describing: "<\(self.classForCoder):\(Unmanaged.passRetained(self).toOpaque())>\n\(result)")
}
// MARK:- ***** if has SWIFTJSON can use this Mesthod *****
required init(_ json: JSON) {
super.init()
self.configValue(json)
}
func configValue(_ json: JSON) {
if let modelInfo = json.dictionary {
let mirror = Mirror(reflecting: self)
for p in mirror.children {
let name = p.label!
if let value = modelInfo[name] {
switch value.type {
case .string:
self.setValue(value.string, forKey: name)
case .number:
self.setValue(value.number, forKey: name)
case .bool:
self.setValue(value.bool, forKey: name)
case .dictionary:
let val = self.value(forKey: name)
if val is BQModel {
(val as! BQModel).configValue(value)
}else {
self.setValue(value.dictionary, forKey: name)
}
case .array:
self.setValue(value.array, forKey: name)
default:
break
}
}
}
}
}
}
extension Array where Element: BQModel {
static func modelArr(arr: Array<Dictionary<String,Any>>) -> Array<Element> {
var result = [Element]()
for dic in arr {
result.append(Element(dic))
}
return result
}
//MARK:- ***** if has SWIFTJSON can use this Mesthod *****
static func modelArr(arr: Array<JSON>) -> Array<Element> {
var result = [Element]()
for json in arr {
result.append(Element(json))
}
return result
}
}
测试
当模型写好后,笔者进行了一个简单的测试。将一万个对象的json字符串作为网络请求返回值,模拟网络请求。
然后分别用HandyJSON和BQModel来进行模型转化
模型代码,保证属性相同
class Person: BQModel {
var name: String?
var age: Int = 0
var std = Student()
}
class Student: BQModel {
var id: String?
var num: Int = 0
var isOld: Bool = false
}
struct ABC: HandyJSON {
var name: String?
var age: Int = 0
var std = ABD()
}
struct ABD: HandyJSON {
var id: String?
var num: Int = 0
var isOld: Bool = false
}
测试代码
//模拟网络请求返回数据JSON化处理
let json = JSON(["name":"asd","age":11,"std":["id":"123","num":12]])
//数据处理
let arrJSON = [JSON](repeating: json, count: 10000)
let arrDict = [Dictionary](repeating: ["name":"asd","age":11,"std":["id":"123","num":12]], count: 10000)
let string = BQTool.jsonFromObject(obj: arrDict)
//时间测试
print("BQModel with JSON")
self.getTime {
let _ = [Person].modelArr(arr: arrJSON)
}
print("BQModel with Dict")
self.getTime {
et data = string.data(using: .utf8)!
let obj = try! JSONSerialization.jsonObject(with: data, options: .allowFragments) as! Array<Dictionary<String,Any>>
let _ = [Person].modelArr(arr: obj)
}
print("HandyJSON")
self.getTime {
let _ = [ABC].deserialize(from: string)
}
测试结果及分析
进行三次测试结果数据如下



有测试数据得出BQModel的效率在这里比HandyJSON较好。需要注意的是笔者缩写的模型考虑情况肯定没有HandyJSON多。所以在通用性方面应该没有HandyJSON做的好(这里也可能是HandyJSON效率比BQModel低的原因)。另外HandyJSON采用内存地址写入,而笔者采用KVC写入,并不完全符合Swift的特性。所以在采用哪种模型方案的时候还是看大家的需求和选择。最后附上笔者Swift工具库连接,有兴趣的朋友可以去看看。如果上述有什么错误请指正,谢谢!
Swift json字典转模型 项目记录的更多相关文章
- iOS彩票项目--第七天,初次读取json数据、KVC转模型技巧、运行时字典转模型以及初步对显示网页的操作并且跟踪标签
一.初次读取json数据 二.KVC转模型技巧,这里的技巧主要解决的是字典中的key 与 模型中有的属性对应不起来的时候 的解决办法 <方法1> <方法2>运行时字典转模型,运 ...
- iOS/macOS推荐个高效苹果开发工具, JSON 转模型代码工具,不再为复杂JSON数据写模型而烦恼,支持Swift/Objective-C,极速转换
CCJSON 是一款运行在macOS上 JSON 转模型代码工具,不再为复杂JSON数据写模型而烦恼,可识别嵌套模型,字典/数组,支持Swift/Objective-C,操作方便,极速转换.下载 效果 ...
- iOS开发——网络篇——JSON和XML,NSJSONSerialization ,NSXMLParser(XML解析器),NSXMLParserDelegate,MJExtension (字典转模型),GDataXML(三方框架解析XML)
一.JSON 1.JSON简介什么是JSONJSON是一种轻量级的数据格式,一般用于数据交互服务器返回给客户端的数据,一般都是JSON格式或者XML格式(文件下载除外) JSON的格式很像OC中的字典 ...
- swift 利用 Reflect(字典转模型)
1. 导入Reflect(字典转模型)框架 2. 让它继承Reflect这个类,如下代码所示: class IWUser: Reflect { /** * 用户的ID */ var idstr:N ...
- iOS字典转模型MJExtension使用
如果项目是纯OC的建议使用,MJExtension是一套字典和模型之间互相转换的超轻量级框架,可以轻松完成: 字典(JSON) --> 模型(Model) 模型(Model) --> 字典 ...
- 利用Runtime实现简单的字典转模型
前言 我们都知道,开发中会有这么一个过程,就是将服务器返回的数据转换成我们自己定义的模型对象.当然服务器返回的数据结构有xml类型的,也有json类型的.本文只讨论json格式的. 大家在项目中一般是 ...
- ios开发网络学习二:URL转码以及字典转模型框架MJExtension的使用
一:url转码,当url中涉及到中文的时候,要考虑转码,用UTF8对中文的url进行转码 #import "ViewController.h" @interface ViewCon ...
- IOS第四天-新浪微博 -存储优化OAuth授权账号信息,下拉刷新,字典转模型
*************application - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOpti ...
- 字典转模型框架 Mantle的使用:国外程序员最常用的iOS模型
Mantle简介 Mantle 是iOS和Mac平台下基于Objective-C编写的一个简单高效的模型层框架. Mantle能做什么 Mantle可以轻松把JSON数据.字典(Dictionary) ...
随机推荐
- O(mn)实现LCIS
序: LCIS即求两序列的最长公共不下降子序列.思路于LCS基本一致. 用dp[i][j]记录当前最大值. 代码实现: /* About: LCIS O(mn) Auther: kongse_qi D ...
- php 中时间函数date及常用的时间计算
曾在项目中需要使用到今天,昨天,本周,本月,本季度,今年,上周上月,上季度等等时间戳,趁最近时间比较充足,因此计划对php的相关时间知识点进行总结学习 1,阅读php手册date函数 常用时间函数: ...
- redis集群添加删除节点
Redis3.0集群添加节点 1:首先把需要添加的节点启动 cd /usr/local/cluster/ mkdir 7006 cp /usr/local/cluster/redis.conf /u ...
- vue2入坑随记(一)
都说Vue2简单,上手容易,但小马过河,自己试了才晓得,除了ES6语法和webpack的配置让你感到陌生,重要的是思路的变换,以前随便拿全局变量和修改dom的锤子不能用了,变换到关注数据本身.vue的 ...
- 关于ie的h5 刷新和ctrl+5刷新 以及图标刷新的问题
最近在做一个表单验证,当表单失去焦点的时候触发错误提示. 可是..... 火狐 欧朋 刷新都没有问题,而在ie edge 用f5刷新的时候 都能记住之前的焦点 造成提示混乱. 问题算是解决: < ...
- [转]Pig与Hive 概念性区别
Pig是一种编程语言,它简化了Hadoop常见的工作任务.Pig可加载数据.表达转换数据以及存储最终结果.Pig内置的操作使得半结构化数据变得有意义(如日志文件).同时Pig可扩展使用Java中添加的 ...
- adesk上架实施--VDC详细配置(深信服论坛转)
1.建立独享桌面资源 1.1通过https://VDCIP:4430登录控制台,VDI设置-->资源管理-->新建独享桌面资源 1.2点击新建,独享桌面资源后显示如下界面 配置完后,往 ...
- bitnami gitlab 安装
安装gitlab需要安装的依赖软件比较多,基于偷懒的原则,从网上找到了bitnami-gitlab-8.7.1-0-linux-x64-installer.run ,集成了所有的相关软件,一键安装,省 ...
- 使用xftp将文件上传至云服务器
一.在云服务器配置FTP服务: 1.在root权限下,通过如下命令安装Vsftp(以centos 系统为例): yum install -y vsftpd. 2. 在启动vsftpd服务之 ...
- Spark操作HBase问题:java.io.IOException: Non-increasing Bloom keys
1 问题描述 在使用Spark BulkLoad数据到HBase时遇到以下问题: 17/05/19 14:47:26 WARN scheduler.TaskSetManager: Lost task ...