HandyJSON阅读笔记

article/2025/9/11 15:19:46

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

HandyJSON仓库: https://github.com/alibaba/HandyJSON

HandyJSON

花了一天半的时间大概阅读学习了一下阿里巴巴开源的HandyJSON库, 只能说是简单的了解一下, Swift Runtime相关的代码没有深入了解. 但是, 收获还是满满的. 一直想深入学习一下面向协议开发的思想, HandyJSON在这方面做得就很不错, HandyJSON是一个完全面向协议开发的库, 主要的逻辑功能都被封装在不同层次协议中, 定义的协议基本都提供了默认的实现.

1.HandyJSON的层次结构

首先看HandyJSON的目录结构如下图所示.

Transforms文件夹下主要包含swift类型和json支持类型相互转换的方法, 比如URL类型转json支持的String类型, urlString转URL类型. 协议的层次结构如下图所示:

Reflection文件夹, 主要包含映射的具体实现过程(目前没有仔细阅读).

其余文件主要包含一些配置文件, 工具类, json转model具体的分类转发递归映射等. 如下图所示:

2.HandyJSON中主要的文件以及其作用

2.1 Export.swift

Export文件对外抛出了几个协议:

  • HandyJSON: 实现序列化反序列化等;
  • HandyJSONEnum: enum的序列化和反序列化;
  • HandyJSONCustomTransformable: 实现协议可自定义转换方式;

2.2 Configuration.swift

  • DeserializeOptions: 定义反序列化选项, 包含caseInsensitive, defaultOptions两个值.
  • HandyJSONConfiguration: HandyJSON配置选项. 包括debug模式和反序列化设置. 变量全部是static类型.

2.3 Logger.swift

根据HandyJSONConfiguration的设置, 打印logo, Error或者Debug或者Verbose.

2.4 Serializer.swift

扩展HandyJSON协议, 将HandyJSON类型转换成JSON类型. 可以将遵守HandyJSON协议的类型转换成转换成JSONType或者JSONString, 转换jsonStirng的过程调用了toJSON()方法. 就是说先转换成json类型的对象, 再转换成json类型的string.

另外扩展了Collection, 代码如下所示. 下面代码优点是包含了递归调用. 这样不管json有多少层次都能够方便的取出所有的值.

public extension Collection where Iterator.Element: HandyJSON {public func toJSON() -> [[String: Any]?] {return self.map{ $0.toJSON() }}public func toJSONString(prettyPrint: Bool = false) -> String? {let anyArray = self.toJSON()if JSONSerialization.isValidJSONObject(anyArray) {do {let jsonData: Dataif prettyPrint {jsonData = try JSONSerialization.data(withJSONObject: anyArray, options: [.prettyPrinted])} else {jsonData = try JSONSerialization.data(withJSONObject: anyArray, options: [])}return String(data: jsonData, encoding: .utf8)} catch let error {InternalLogger.logError(error)}} else {InternalLogger.logDebug("\(self.toJSON()) is not a valid JSON Object")}return nil}
}

2.5 Deserializer.swift

扩展SwiftJSON类型, 将json字符串或者json对象序列化成一个类对象.

扩展中提供很多deserialize方法, 这里的方法做一些基本的判断处理, 之后具体的映射过程被放在_ExtendCustomModelType协议中.

2.6 TransformType.swift

定义了json支持的数据类型和swift中数据类型的转换.

2.7 Measuable.swift

_Measurable协议, 定义支持操作内存基本的方法.

2.8 Transformable.swift

_Transformable继承自_Measurable, 主要作用是将不同类型的转换过程分发到不同的实现中去.

学习与进阶

1. associatedtype和typealias

在定义协议时候可以通过associatedtype关键字声明一个或者多个关联类型作为协议定义的一部分, 然后在协议的实现中通过typealias给关联类型赋值是非常有用的, 这样可以将协议中方法参数具体类型的声明延迟到具体的方法实现中去.

2.url转码

有时候url中包含汉子会导致打不开网页, 找不到网址等等的麻烦, 可以通过下面的方法addingPercentEncoding给String转码, 这样汉子会变成带有%号的符号, 这样就可以正常访问了.

guard let escapedURLString = URLString.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) else {return nil}

3.关于协议的用法

如下代码是苹果API中RawRepresentable的定义和部分实现. 这段代码好在在协议中定义RawValue类型, 并将RawValue具体类型的定义延迟到了具体实现中. 在实现协议时候可以通过where关键字, 判断RawValue类型并做不同的实现.

public protocol RawRepresentable {associatedtype RawValuepublic init?(rawValue: Self.RawValue)public var rawValue: Self.RawValue { get }
}extension RawRepresentable where Self.RawValue == Bool {public func encode(to encoder: Encoder) throws
}

4.Self关键字

'Self' is only available in a protocol or as the result of a method in a class

  1. Self可以用于协议(protocol)中限制相关的类型
  2. Self可以用于类(Class)中来充当方法的返回值类型
//第一种用法
protocol Copyable {func copy() -> Selffunc clamp(intervalToClamp: Self) -> Self
}//第二种用法
class A: Copyable {class func calssFunc() -> Self {let type = selfprint(type)let result = type.init()return result}}

在协议中Self代表本类型的一个实例, Self.self可以代表一个类型本身.

5.RawRepresentable协议

一个可以用来表示另一种类型的类型. enum实现了RawRepresentable协议, 因此class EnumTransform<T: RawRepresentable>中的T可以看成是enum类型(当然可以是任何实现RawRepresentable协议的类型).

//RawRepresentable协议的声明
public protocol RawRepresentable {associatedtype RawValuepublic init?(rawValue: Self.RawValue)public var rawValue: Self.RawValue { get }
}

6.swift预编译设置

如下代码所示, 在swift中一样可以通过#if, #else, #endif这样的方法判断不同的系统, 手机型号等等等

#if os(iOS) || os(tvOS) || os(watchOS)
import UIKit
#else
import Cocoa
#endif

7.声明协议标准

如下所示, 如果一个协议有默认实现时候, 一般情况下我们可以将协议方法的定义和实现全部放在扩展中, 这样遵守协议时候就不需要实现任何方法(纯swift中协议中方法必须全部实现).有看到swift语言API和很多三方库都是这么做的.

protocol _TestProtocol {}
extension _TestProtocol {func testRun() {print("run")}
}
extension UIView: _TestProtocol {func testRun() {print("UIView run")}
}

8.associatedtype和typealias关键字

8.1 重命名

typealias关键字从来为已经存在的类型重新定义名字, 通过命名, 可以让代码变得更加清晰. 主要功能是增加代码的可读性.

typealias与泛型, typealias是单一的, 也就是说你必须指定将某个特定的类型通过typealias赋值为新的名字, 而不能将整个泛型类型进行重命名.

//如下代码是不能编译通过的
class Person<T> {}  
typealias Woker = Person  
typealias Worker = Person<T>  //如下, 如果我们在别名中也引入泛型, 则是可以编译通过的
class Person<T> {}  
typealias Woker = Person  
typealias Worker<T> = Person<T>  

8.2 组合协议类型

如下所示, 可以通过&运算符将多个协议组合在一起并重命名.

protocol Cat {}  
protocol Dog {}  
typealias Pat = Cat & Dog  

8.3 associatedtype关联类型

定义一个协议时, 有时候声明一个或者多个关联类型作为协议的一部分会十分有用. 关联类型为协议中的某个类型提供了一个占位名(或者说别名), 其代表的实际类型在协议被采纳时才会被指定. 你可以通过associatedtype关键字来指定关联类型.

//模型  
struct Model {  let age: Int  
}  //协议,使用关联类型  
protocol TableViewCell {  associatedtype T  func updateCell(_ data: T)  
}  //遵守TableViewCell  
class MyTableViewCell: UITableViewCell, TableViewCell {  typealias T = Model  func updateCell(_ data: Model) {  // do something ...  }  
}  

疑问

1.TransformType协议中func transformFromJSON(_ value: Any?) -> Object? value为什么不用JSON声明呢? 用JSON声明之后, 遵循协议时候不是不用转换类型了么?

public protocol TransformType {associatedtype Objectassociatedtype JSONfunc transformFromJSON(_ value: Any?) -> Object?func transformToJSON(_ value: Object?) -> JSON?
}

转载于:https://my.oschina.net/whforever/blog/1617465


http://chatgpt.dhexx.cn/article/HkOGkjqt.shtml

相关文章

iOS swift Alamofire+HandyJSON网络框架封装

iOS swift AlamofireHandyJSON网络框架封装 我们在学习Objective_C时使用的网络框架是AFNetworkingMJExtension&#xff0c;而在swift中AlamofireHandyJSON取代了它&#xff0c;如果你是第一次学习和尝试封装swift的网络框架&#xff0c;可能会遇到一些坑&#xff0c;但踩过这些…

Swift 类似HandyJSON解析Struct

Swift 类似HandyJSON解析Struct HandyJSON从源码解析Struct获取TargetStructMetadata获取TargetStructDescriptor实现TargetRelativeDirectPointerFieldDescriptor和FieldRecordfieldOffsetVectorOffset计算偏移量 代码的验证 HandyJSON HandyJSON是阿里开发的一个在swift上把…

HandyJSON:Swift语言JSON转Model工具库

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

HandyJSON和SwiftyJSON的应用

2019独角兽企业重金招聘Python工程师标准>>> 1. HandyJSON的应用 想要通过HandyJSON实现序列化和反序列化, 必须实现HandyJSON协议, 不需要继承NSObject对象, 实现协议必须实现public init(){} 方法. 序列化和反序列化支持struct和enumerate类型. HandyJSON可支持非…

(时频分析学习)Week01:傅里叶级数,S变换与广义S变换

学习内容:了解了傅里叶变换相关内容,掌握了基本的傅里叶函数的性质、特性和背景。了解S变换和广义S变换的公式和具体含义。 s变换: (在"基准"论文中)意义: 公式: (傅里叶原公式),再有ω2πf 和 f(t)x(t)w(τ-t)进行转换 在另一篇论文中: 广义s变换: 加上了一点关…

解构变换矩阵:如何使变换矩阵分解为位移(T),旋转(R),缩放(S)矩阵

解构变换矩阵 给定一个转换的复合矩阵&#xff0c;关于组成该转换的任何单个转换的信息就会丢失。 我们如果有一个复合矩阵&#xff0c;怎么能使其分解为TRS三个矩阵呢&#xff1f;即如何完成下述变化&#xff1a; 其中M是给定的变换矩阵&#xff0c;T是平移矩阵&#xff0c;R是…

SS2022-Z变换-性质-什么是z变换的时移特性?

简 介&#xff1a; 本文介绍了z变换时移特性。 关键词&#xff1a; z变换&#xff0c;时移特性 #mermaid-svg-EnOHOPxDmWhoesDM {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-EnOHOPxDmWhoesDM .error-icon{fill:#…

【转】传递函数中拉普拉斯变换的s是用来干什么的?

自控书里一上来就到处是s,这个s到底是个什么东西? 好我知道s是拉普拉斯变换出来的,但为什么要搞这样一个变换?这个s的物理意义是什么? 为什么传递函数的极点决定系统的性质? …… 要解答这些问题,首先要从拉普拉斯变换讲起。 -----------------------------------------…

S变换的Python代码

S变换的Python代码 S变换简介S变换Python程序 S变换简介 S变换&#xff0c;又称为Stockwell变换&#xff0c;由R. G. Stockwell于1996年提出。具体的定义如下&#xff1a; S变换在傅里叶域的表示形式为&#xff1a; 离散的S变换为&#xff1a; S变换克服了短时傅里叶变换固…

S变换画图

The S -transform with windows of arbitraryand varying shape 想画如上的三张图&#xff0c;可是问题 &#xff08;1&#xff09;滤波窗口的平滑实现 The filter (applied to the full 200£400 S-transform matrix)is constructed in Matlab by constructing a two-dime…

【广义S变换】一维广义S变换对非平稳信号处理的matlab仿真

1.软件版本 matlab2013b 2.本算法理论知识 参考文献: 《广义S变换时频分析的应用研究》 《时频分布与地震信号谱分析研究》 《非平稳信号广义S不变换及其在SAR图像分析中的应用研究》 《S变换时变滤波在去噪处理中的应用研究》 《广义S变换域时频特征分析及微弱目标检测…

频域/s域/z域三大变换的性质对比

本文主要介绍三大变换&#xff08;傅里叶变换、拉普拉斯变换及Z变换&#xff09;的性质对比及其常用信号变换。

S域到Z域变换和差分方程

1.s域的传递函数 G(s) 2 / (1500s 1) * exp(-100s) matlab 里面的命令是 sys tf(2,[1500,1],inputdelay,100) 得到 2 exp(-100*s) * ---------- 1500 s 1 2.求 Z域传递函数 dsy c2d(sys,10,z) % 10 为间隔采样时间 得到 0.01329 z^(…

matlab实现从s域变成z域、matlab实现长除法逆z变换实例

今天在复习微型计算机控制技术这门课时&#xff0c;感觉还是和当初学习时一样&#xff0c;计算量有点大。 主要是体现在&#xff1a;&#xff08;1&#xff09;、连续S域到离散Z域的变换。&#xff08;2&#xff09;、在画数字控制器和输出波形前对Y(z)和U(z)的长除法化简。 …

s域和z域变换笔记

连续函数 1、常见信号的拉普拉斯变换&#xff1a; 脉冲信号 δ&#xff08;t&#xff09;------------1 阶跃信号 μ&#xff08;t&#xff09;------------- 斜坡信号 t ------------------ 加速度信号 ---------------- 指数类信号 --------------- 正弦…

傅里叶变换(FS、FT、DTFT、DFT、DFS、FFT)、拉普拉斯变换和Z变换

傅里叶变换的目的&#xff1a;时域转为频域&#xff0c;滤波&#xff0c;求解微分方程等 1. FS&#xff08;Fourier Series&#xff09; 傅里叶级数&#xff1a;时域周期连续&#xff0c;频域离散。 前提&#xff1a;任何信号都可以看作是无限多的正弦波的叠加。 时域&#x…

Z变换

信号与系统的分析方法 可以分为两大类&#xff1a;时域分析和变换域分析 1.时域分析法&#xff1a; &#xff08;1&#xff09;连续时间信号与系统&#xff1a;信号的时域运算、分解&#xff0c;微分方程的经典解法&#xff1b;卷积积分 &#xff08;2&#xff09;离散时间…

matlab实现S域到Z域变换

传递函数如下: Z变换: 代码如下: %构造传递函数 h tf(10, [0.2 1 0]) %Z变换 zh c2d(h, 0.2,zoh) %得到分子分母系数 [num den] tfdata(zh, v) %得到零极点 [z, p, k] tf2zpk(num, den) 运行结果如下: h 10-----------0.2 s^2 sContinuous-time transfer functio…

S变换在特征提取中的使用

S变换 S变换采用高斯窗函数且窗宽与频率的倒数成正比&#xff0c;免去了窗函数的选择和改善了窗宽固定的缺陷&#xff0c;并且时频表示中各频率分量的相位谱与原始信号保持直接的联系&#xff0c;S变换具有良好的时频特性&#xff0c;适合用S变换对信号的一些时频与特征进行提取…

S变换

哈哈&#xff0c;这两天在整理时频分析的方法&#xff0c;大部分参考网上写的比较好的资料&#xff0c;浅显易懂&#xff0c;在这谢过各位大神了&#xff01; 今天准备写下S变换&#xff0c;由于网上资料较少&#xff0c;自己尝试总结下&#xff0c;学的不好&#xff0c;望各位…