对于开发的人员来说,接受后台的数据,并转换成自己的数据模型是常见的事情。但是作为苹果开发者,并没有一个很好的工具去直接转换,必须借助与第三方的开发的库。那么比较好用的有YYModel、MJExtension。当然还有其他的库。但是有个问题,对于第三方库,如果使用过多对于我们开发者来说并不是一件好事。简单分析一下:优点:功能强大,使用方便,提高开发效率,相对较安全出现bug几率较小。缺点:受限于第三方(主要是版本),如果有bug不容易修改,甚至只能官方修改,增大开发包,使用过多容易导致编译速度极慢,实际用到的功能很少。基于以上选择,使不使用第三方自己斟酌,我们这篇文章,在这不做讨论,对于swift而言,我们这篇文章主要讲怎么使用官方的Codable转换成自己的模型。下面进入正题。

swift引入了Codable编码与解码的功能,简单来说就是支持把一个json,转成自己创建并遵从Codable协议的一个数据模型,可以是类,也可以是结构体struct,对于结构体这个是第三方所没有的一个功能。苹果官方推荐使用结构体,方便,安全,占用内存少,还不用担心内存释放问题,好处多多。我们针对struct来说一下。

首先我们先创建一个json数据:

{"name": "张三","age": 20,"birthday": "1990-06","location": "中国","job": "教师"
}

然后我们创建一个结构体模型接收这个数据:

struct UserModel: Codable {var name = "";var age = 0;var birthday = "";var location = "";var job = "";
}

说明这个结构体模型必须实现Codable协议。

然后我们去进行decode解码:

let dict = """
{"name": "张三","age": 20,"birthday": "1990-06","location": "中国","job": "教师"
}
"""
let decode = JSONDecoder();
if let data = dict.data(using: .utf8) {let item = try? decode.decode(UserModel.self, from: data);print("item: \(item)");
}

同过打印我们发现,可以正常输出struct的各个值,使用起来就是这么简单。

2.对于复杂的json我们也是可以解析的。比如下面的json:

{"name": "张三","age": 20,"birthday": "1990-06","location": "中国","job": "教师","students": [{"name": "小丽","age": 12,"id": 1234,"sex": "女"},{"name": "小万","age": 11,"id": 1235,"sex": "男"},{"name": "小明","age": 14,"id": 1237,"sex": "男"}]}

上边这个是比较复杂的,一个对象包括了数组,数组里面又有对象,那么对于这个struct模型我们可以这样创建:

struct UserModel: Codable {var name = "";var age = 0;var birthday = "";var location = "";var job = "";var students: [StudentsModel]!
}struct StudentsModel: Codable {var name = "";var age = 0;var id = 0;var sex = "";
}

使用起来还是上边的那个方法我们可以看到students打印出来的是个数组。

但是有时候,情况并不我们想象中的那么完美,尤其是在命名规则上,后台有可能会出现带下滑杠的命名方式比如:student_name等形式,而swift一般是驼峰是命名比如:studentName,这就带来了一个问题,这两个显示是不匹配的,那么我们怎么解决这个问题呢,比如我们有如下的json数据:

{"name": "张三","phone_number": 18467898765,"pic_url": "中国"
}

这个时候我的需要把手动把属性和值对应起来。

struct UserModel: Codable {var name = "";var phoneNumber = 0;var picURL = "";enum UserKeys: String, CodingKey {case phoneNumber = "phone_number"case picURL = "pic_url"case name = "name"}init(from decoder: Decoder) throws{let value = try? decoder.container(keyedBy: UserKeys.self);phoneNumber = (try? value?.decode(Int.self, forKey: .phoneNumber)) ?? 0;picURL = (try? value?.decode(String.self, forKey: .picURL)) ?? "";name = (try? value?.decode(String.self, forKey: .name)) ?? "";}
}

从上面也可以看出,当键和值的类型不一样的时候我们也是可以转换的。

swift的Codable很简单也很强大,如果我们在实际开发的时候,后台返回来的数据并不是完整的,如果没有那个值可能就不返回来了,这个时候我们上面的问题就暴露出来了。具体是什么错误呢。我们把数据json的name去掉,并改成如下的形式。

数据:{"age": 12,"birthday": "2000-01"
}模型:struct UserModel: Codable {var name = "";var age = 0;var birthday = "";
}

测试方法我们也变一下:

let decode = JSONDecoder();if let data = stringValue.data(using: .utf8) {do {let item = try decode.decode(UserModel.self, from: data);print("item: \(item)");} catch  {print("error =\(error)");}}

会打印如下的错误信息:

error =keyNotFound(CodingKeys(stringValue: "name", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: \"name\", intValue: nil) (\"name\").", underlyingError: nil))

就是我们定义的name是必须有的,但是后台没有返回所以就出错了,这个时候我们要定义成可选类型,如下:

struct UserModel: Codable {var name: String?var age: Int?var birthday: String?
}

这个时候就可以放心的使用了,发现成功答应值,只是name是空。

其实我们发现这些属性的值我们使用过程中一般都是读取,为了更好的表达这个意图,我们一般定义成下面这样,保证了数据的安全:

struct UserModel: Codable {let name: String?let age: Int?let birthday: String?
}

为了更好的使用这个Codable这个特性,我们可以封装一下,给JSONDecoder添加一个扩展,具题如下:

extension JSONDecoder {class func jsonDecoder<T: Codable>(_ type: T.Type,from data: Data?) -> T? {guard let data = data else {return nil;}let json = JSONDecoder();var jsonItem: T? = nil;do {jsonItem = try json.decode(type, from: data)} catch {printObject("data convert json error: \(error)");}return jsonItem;}class func jsonDecoder<T: Codable>(_ type: T.Type,fromAny data: Any?) -> T? {if let data = data as? Data {return jsonDecoder(type, from: data);}guard let data = data else {return nil;}if let stringValue = data as? String {return jsonDecoder(type, from: stringValue.data(using: .utf8));}let jsonData = try? JSONSerialization.data(withJSONObject: data, options: .prettyPrinted);return jsonDecoder(type, from: jsonData);}
}

这样使用起来就方便了许多。好了对于Codable的使用我就说这么多,还有编码也是一样的,可以自己探索一下。

还是那句老话:学习的路上,总不缺少努力的人。祝你越来越

swift 5.1 Json转换之Codable相关推荐

  1. JSON转换和毫秒时间

    JSON转换和毫秒时间 String dataId = "0000000000003000-0001";String baisc= " { "+ " ...

  2. [转] JSON转换

    转载自:http://www.360doc.com/content/12/0413/14/9529755_203286509.shtml# JSON简介 JSON(JavaScript Object ...

  3. Python JS Jquery Json 转换关系

    一.JS对象与JSON格式数据相互转换 目前的项目数据交互几乎都用JQuery,所以处理流程是: 前端页面数据->JS对象->jQuery提交->python处理,另外一种就是倒过来 ...

  4. json转php数组 在线,PHP如何将JSON转换成数组/对象

    在PHP中可以使用json_decode()函数将JSON编码的字符串转换为适当的PHP数据类型.默认情况下,json_decode()函数将返回一个对象:但是,可以指定第二个参数为一个布尔值true ...

  5. Python-jsonpath使用和json转换

    (一)JSONPath-JSON的XPath JSONPath表达式始终以与XPath表达式与XML文档结合使用的相同方式引用JSON结构.由于JSON结构通常是匿名的,并且不一定具有"根成 ...

  6. 前后台json交互,以及数据库json转换——PHPThinkphp5.1

    0. 前言 最近在做一个项目,一个考试系统.后台采用的核心技术是PHP+Thinkhp5.1+Mysql. 要求前后台之间用json数据交互,后台需要将前台json关键字段接收,然后查询数据库,返回相 ...

  7. 关于json 转换BigDecimal精度丢失问题

    今天在转换一个关于金额字段发现一个关于json转换的bug  目前尚未深入观察 问题: 如果金钱为bigdecimal json转换后不会丢失精度 但是通过@responsebody 返回到前端后发现 ...

  8. javabean与json转换(fastjson与jackson两个版本)

    [README] 本文演示了 javabean与json转换的开发方式: 要想 javabean的属性名 与 json的字段名不一致,也是可以转换的: 之前需要引入 ali.fastjson < ...

  9. python字典与json转换_python字典与json转换的方法总结

    在python中json分别由列表和字典组成,本文主要介绍python中字典与json相互转换的方法.使用json.dumps可以把字典转成json字符串.使用json.loads可以把json字符串 ...

最新文章

  1. CCNA(Stand-ALONE)Lab 12-Static Routes
  2. 深度学习100例-卷积神经网络(CNN)识别神奇宝贝小智一伙 | 第16天
  3. hibernate 多对一外键注解
  4. 三星Galaxy S21+真机上手视频曝光:外观彻底无悬念
  5. android升序降序按钮,创建一个按钮,将排序MYSQL查询升序和降序
  6. java字符串数字统计_对字符串进行简单的字符数字统计 探索java中的List功能
  7. mysql lru scan depth_如何解决mysql警告:“ InnoDB:page_cleaner:1000毫秒的预期循环用了XXX毫秒。设置可能不是最佳的”?...
  8. 20.23 20.4 20.5告警系统邮件引擎(上中下);20.26 运行告警系统
  9. MySQL的LIKE模糊查询优化
  10. BZOJ2748[HAOI2012] 音量调节
  11. java mschart_vb之mschart控件小结
  12. 机器视觉入门知识总结
  13. 微信小程序开发者工具平台+Hbuilder开发平台下载
  14. Spy++ —— 窗口、消息查看分析利器
  15. 万网域名证书如何查询下载_备案域名证书获取
  16. vue3+element plus下面,自定义el-table表格标题
  17. Java如何设置word中某段文字的字体/段落样式
  18. 网易5天python编程课_网易云课堂上自学编程?
  19. 汇编语言实现 大小写字母转换
  20. cuda和GPU驱动的关系

热门文章

  1. 四足机器人不同步态研究
  2. 杂学——密码学、中国余数定理、韩信点兵法、取模运算
  3. 文件I/O与系统编程
  4. pdf文件没有加密保护,仍然不能编辑的解决办法
  5. 鸡尾酒排序算法c语言源代码,排序算法 -鸡尾酒排序
  6. 加快Win7整体运行速度的12个小技巧
  7. 手写坦克大战联网版(持续更新)
  8. 程序员,工作后还能找到女朋友吗?
  9. 【网络编程】多个服务器的情况:nginx实现反向代理、nginx基于反向代理实现负载均衡
  10. C51#学习笔记01#| Keil软件的使用入门教程