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) ...
随机推荐
- 使用Spire.Doc组件利用模板导出Word文档
以前一直是用Office的组件实现Word文档导出,但是让客户在服务器安装Office,涉及到版权:而且Office安装,包括权限配置也是比较麻烦. 现在流行使用第三方组件来实现对Office的操作, ...
- 将sublimeText添加到鼠标右键菜单栏
将sublimeText添加到鼠标右键菜单栏主要是写一个注册表的文件,将这个注进去,首先你需要清楚你的sublimeText软件的安装路径,然后改一下下面这段代码就可以了 Windows Regist ...
- NancyFx 2.0的开源框架的使用-Stateless
同样和前面一样新建一个空的Web项目,都在根目录添加Module,Models,Views文件夹 添加Nuget包 在Models文件夹里面添加UserModel类 public string Use ...
- springcloud(二):注册中心Eureka
Eureka是Netflix开源的一款提供服务注册和发现的产品,它提供了完整的Service Registry和Service Discovery实现.也是springcloud体系中最重要最核心的组 ...
- JAVA并发编程实战---第三章:对象的共享
在没有同步的情况下,编译器.处理器以及运行时等都可能对操作的执行顺序进行一些意想不到的调整.在缺乏足够同步的多线程程序中,要对内存操作的执行顺序进行判断几乎无法得到正确的结果. 非原子的64位操作 当 ...
- Java 程序员快速上手 Kotlin 11 招
欢迎大家关注腾讯云技术社区-博客园官方主页,我们将持续在博客园为大家推荐技术精品文章哦~ 作者:霍丙乾 近经常会收到一些 "用 Kotlin 怎么写" 的问题,作为有经验的程序员, ...
- js实用方法记录-简单cookie操作
js实用方法记录-简单cookie操作 设置cookie:setCookie(名称,值,保存时间,保存域); 获取cookie:setCookie(名称); 移除cookie:setCookie(名称 ...
- Git版本控制,rsync同步文件,完成线上部署
之前项目开发完成,测试阶段,借着此时,由于公司暂时用两台aliyun ecs 做业务层,所以每次都需要同步线上文件,进而想着搞一搞服务器端(小公司,新项目,先小搞一把),搭建一套小的版本控制上线的 ...
- JVM学习笔记二:JVM参数
所有线程共享的内存主要有两块:堆内存和方法区. 其中堆内存分为两块:新生代Young generation(Eden区.From Survivor区.To Survivor区).老年代Tenured ...
- git常用命令记录
配置本地仓库 git config --global user.name.git config --global user.email 查看配置详情 git config -l 初始仓库 git in ...