自从开始使用Swift做项目,一直都在使用HandyJSON,不可否认,HandyJSON在Swift4.0以前是个好东西,也尝试过其它json转mode的工具,最终发现还是HandyJSON最好用. 去年Swift4.0发布之后,一个最有趣的变化就是Codable协议. 一直都知道Codable来实现json转model,不但效率高,并且简单易用, 但是一直拖到最近才简单封装个小工具,为什么呢? ?!!!

在工具的封装上,参考了HandyJSON的部分代码,在使用HandyJSON过程中,一直都觉得designatedPath是一个很牛逼的存在,开发效率提升了不是一个量级,于是这里也参考HandyJSON中designatedPath的实现代码,并根据Codable的需要改造成fileprivate func getInnerObject(inside jsonData: Data?, by designatedPath: String?) -> Data?方法. 在这里感谢HandyJSON开发组.

Codable扩展全部代码如下所示.100余行的代码前后花费一天多的时间. 当了解到google工程师日均一百多行的代码量,我觉得这速度还可以吧. 在代码质量和阅读质量上不敢说有多好,我只是按照自己认为最好的方式来做,如果有哪里不当或者可以用更好方法解决的地方,烦请各位告知,彼此交流学习.

Codable协议扩展实现代码如下所示:

//
//  CodableHelper.swift
//  CodableDemo
//
//  Created by Walden on 2018/5/7.
//  Copyright © 2018年 Walden. All rights reserved.
//import Foundation//扩展Encodable协议,添加编码的方法
public extension Encodable {//1.遵守Codable协议的对象转json字符串public func toJSONString() -> String? {guard let data = try? JSONEncoder().encode(self) else {return nil}return String(data: data, encoding: .utf8)}//2.对象转换成jsonObjectpublic func toJSONObject() -> Any? {guard let data = try? JSONEncoder().encode(self) else {return nil}return try? JSONSerialization.jsonObject(with: data, options: .allowFragments)}
}//扩展Decodable协议,添加解码的方法
public extension Decodable {//3.json字符串转对象&数组public static func decodeJSON(from string: String?, designatedPath: String? = nil) -> Self? {guard let data = string?.data(using: .utf8),let jsonData = getInnerObject(inside: data, by: designatedPath) else {return nil}return try? JSONDecoder().decode(Self.self, from: jsonData)}//4.jsonObject转换对象或者数组public static func decodeJSON(from jsonObject: Any?, designatedPath: String? = nil) -> Self? {guard let jsonObject = jsonObject,JSONSerialization.isValidJSONObject(jsonObject),let data = try? JSONSerialization.data(withJSONObject: jsonObject, options: []),let jsonData = getInnerObject(inside: data, by: designatedPath)  else {return nil}return try? JSONDecoder().decode(Self.self, from: jsonData)}
}//扩展Array,添加将jsonString或者jsonObject解码到对应对象数组的方法
public extension Array where Element: Codable {public static func decodeJSON(from jsonString: String?, designatedPath: String? = nil) -> [Element?]? {guard let data = jsonString?.data(using: .utf8),let jsonData = getInnerObject(inside: data, by: designatedPath),let jsonObject = try? JSONSerialization.jsonObject(with: jsonData, options: .allowFragments) as? [Any] else {return nil}return Array.decodeJSON(from: jsonObject)}public static func decodeJSON(from array: [Any]?) -> [Element?]? {return array?.map({ (item) -> Element? inreturn Element.decodeJSON(from: item)})}
}/// 借鉴HandyJSON中方法,根据designatedPath获取object中数据
///
/// - Parameters:
///   - jsonData: json data
///   - designatedPath: 获取json object中指定路径
/// - Returns: 可能是json object
fileprivate func getInnerObject(inside jsonData: Data?, by designatedPath: String?) -> Data? {//保证jsonData不为空,designatedPath有效guard let _jsonData = jsonData,let paths = designatedPath?.components(separatedBy: "."),paths.count > 0 else {return jsonData}//从jsonObject中取出designatedPath指定的jsonObjectlet jsonObject = try? JSONSerialization.jsonObject(with: _jsonData, options: .allowFragments)var result: Any? = jsonObjectvar abort = falsevar next = jsonObject as? [String: Any]paths.forEach({ (seg) inif seg.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) == "" || abort {return}if let _next = next?[seg] {result = _nextnext = _next as? [String: Any]} else {abort = true}})//判断条件保证返回正确结果,保证没有流产,保证jsonObject转换成了Data类型guard abort == false,let resultJsonObject = result,let data = try? JSONSerialization.data(withJSONObject: resultJsonObject, options: []) else {return nil}return data
}

CodableHelper工具的使用也是非常简单的,代码如下所示:

//首先定义一个结构体Person用来表示数据Model
struct Person: Codable {var name: String?var age: Int?var sex: String?
}//1.jsonString中获取数据封装成Model
let p1String = "{\"name\":\"walden\",\"age\":30,\"sex\":\"man\"}"
let p1 = Person.decodeJSON(from: p1String)//2.jsonString中获取数据封装成Array
let personString = "{\"haha\":[{\"name\":\"walden\",\"age\":30,\"sex\":\"man\"},{\"name\":\"healer\",\"age\":20,\"sex\":\"female\"}]}"
let persons = [Person].decodeJSON(from: personString, designatedPath: "haha")//3.对象转jsonString
let jsonString = p1?.toJSONString()//4.对象转jsonObject
let jsonObject = p1?.toJSONObject()

目前存在问题:

  1. Model中定义的数据类型和jsonString中数据类型不对应时候会导致解析失败;
  • 转载请注明出处

转载于:https://www.cnblogs.com/dev-walden/p/9008866.html

Codable实现json转Model,是时候干掉HandyJSON了!相关推荐

  1. HandyJSON:Swift语言JSON转Model工具库

    背景 JSON是移动端开发常用的应用层数据交换协议.最常见的场景便是,客户端向服务端发起网络请求,服务端返回JSON文本,然后客户端解析这个JSON文本,再把对应数据展现到页面上. 但在编程的时候,处 ...

  2. swift 访问oracle,Swift实现JSON转Model - HandyJSON使用讲解

    很多时候,我们从服务端请求下的数据都是Json格式,我们需要拿这些数据显示到我们的UI界面. 因此,我们的做法基本都会先将json转为方便使用的数据模型,或者也可以直接转字典解决. 在OC中,我们有很 ...

  3. Spring控制器响应(action)请求的几种处理方式,如返回JSON,MODEL MODELVIEW,STRING

    2019独角兽企业重金招聘Python工程师标准>>> Controller: package **.web.controller;import java.io.IOExceptio ...

  4. iOS端JSON转Model链式编程框架SuperKVC使用方法与原理

    背景 在client编程中.字典转模型是一个极为常见的问题,苹果提供了KVC来实现NSDictionary到Model的注入,可是KVC仅仅能进行单层浅注入.且无法处理类型转换.key与属性名不正确应 ...

  5. iOS Mac JSON To Model

    2019独角兽企业重金招聘Python工程师标准>>> NSString * jsonPath=[[[NSBundle mainBundle] resourcePath] strin ...

  6. 打开json文件的工具_Flutter中JSON转Model——在线生成

    在开发过程中,我们一般都是使用插件或工具一键生成实体类的,这样极大的提高了开发效率,目前我们可以通过在线生成的方式来一键生成Dart类. 1. 使用json_to_dart 地址: https://j ...

  7. SAP UI5 视图如何使用工程里的 sample data 作为 JSON model 的数据源

    在本地工程文件里,新建一个 model 文件夹,里面包含一个 mock.json 文件: 运行时,该文件被加载的路径为 /model/mock.json: 也可以直接写成: createOrdersM ...

  8. 自定义组件封装之-如何使用SwfityJSON实现JSON/Model相互转换

    最近在学习Swift的各种框架,在我的另一篇Swift框架学习之-数据解析SwiftyJSON,已经介绍过了如何使用SwfityJSON这个牛逼的纯Swift写的框架,这里就不作过多介绍,主要来说说我 ...

  9. Codable 基本使用

    Codabel JSON转模 官方文档:Using JSON with Custom Types JSON 介绍:JavaScript Object Notation Codable 是 Swift ...

最新文章

  1. LINQ技术、EF技术都出来蛮久了,软件开发者、软件公司是否还有必要有自己的代码生成器?...
  2. [问答题] 考SQL语句的题,题太长了,实在不好回忆了。
  3. 遇见王沥川的人生感悟_23岁酱油泡饭默默无闻,31岁逆袭人生,王彦霖有何魅力?...
  4. python的socket模块_python模块:socket模块
  5. QML工作笔记-在Row布局中如何进行稍许移动(图片Row布局会遇到)
  6. ubuntu 下groovy 安装配置
  7. leetcode71 (2022.1.6)
  8. MTK 驱动---(10) emmc总线
  9. MySQL数据库---数据库管理
  10. CSS布局:图片在DIV中上下左右居中(水平和垂直都居中)
  11. 【迁移学习】PointDAN: A Multi-Scale 3D Domain Adaption Network for Point Cloud Representation
  12. (附源码)springboot自习室座位预约系统 毕业设计674156
  13. Pandas数据分析库(2)Python数据分析
  14. 图像几何校正 (介绍Image to Image几何校正详细步骤)
  15. 做外贸有没有好的软件?
  16. 计算机考研2018大纲,2018计算机考研大纲(word版)
  17. 中国历史上三大盛世的理性审视
  18. 谷歌翻译 google translation API github开源 实践
  19. 计算机专业口号 十六个字,计算机学院标语口号,16字计算机与信息学院运动会口号...
  20. 辣椒app软件测试,辣椒视频(test flight)官方版

热门文章

  1. 一个学员去了互联网大厂一个笔试题分享
  2. 瓜子二手车面试java
  3. 浅谈Google SEO入行
  4. linux:文件操作(open、write/read、lseek、close)
  5. 模型稳定度指标PSI
  6. (超实用、简单明了)Mysql变量定义与赋值
  7. Python爬虫笔记——解析json数据(以周杰伦歌单为例)及Headers
  8. 无尽的任务1-仿CNZZ的流量统计,完成80%(更新1次)
  9. 小信号放大电路的频率特性
  10. rpc服务器不可用桌面图标消失,rpc服务器不可用,教您rpc服务器不可用怎么办