【规范建议】服务端接口返回字段类型与iOS端的解析
一、本文档的写作目的
App需要跟产品、UI、后台、服务器、测试打交道,app的产出是其他端人员产出的综合体现。与其他端人员沟通就像是开发写接口,也就是面向接口编程的思想。
本文档讲解针对的是服务端返回数据时使用的字段数据类型如何选择、iOS端将JSON数据转模型的时候用什么类型来定义对应的属性。
二、本文档的使用范围
首先介绍下在本文档中使用的技术领域。
1、服务端使用的是C#语言
2、Api接口文档自动生成
3、采用的是JSON数据传输格式
4、iOS使用的是Objective-C语言举例
上面提到的技术范围并不影响到本文档的推广。首先,在项目内部严格执行。后续可以在公司其他项目组中结合实际情况完成落地。
三、正文
服务器返回的类型 | 使用领域 | iOS端模型中属性类型 | NSLog输出格式 |
integer | 表示整型数据 | NSInteger | %ld |
decimal number | 数据相关的最好使用浮点型 | CGFloat | %f、%0.2f |
boolean | 判断是否的数据 | BOOL | %ld |
string | 文本信息 | NSString | %@ |
date | 时间信息(要求服务器的dateFormat统一) | NSDate | %@ |
Enum | 枚举 | Enum | %ld |
对象 | 里面的内容多处使用,封装成对象 | Model类 | %@ |
Collection of string | 基本数据类型的集合 | NSArray<NSString *> | %@ |
Collection of 对象 | 对象类型的集合 | NSArray<类名 *> | %@ |
简单的表格罗列出来的信息总是意犹未尽,有几个重要的信息说明如下:
(1)使用NSInteger、CGFloat、BOOL,而不要使用int、float、double、bool甚至是NSNumber。
解释:
首先,不使用int而使用NSInteger等是属于语言特性逻辑,NSInterger对int多了处理,比如会结合运行平台使用int_32\int_64。
然后不使用NSNumber的原因是,NSNmuber采用的是类簇装箱拆箱,NSNumber只是中间量,表述不清楚。JSON转字典再转模型,OC语言中字典中的的元素必须是对象类型,因此使用NSNumber放置在字典中,但是在字典转模型的时候不还原它的装箱前的本来面目,对使用该模型的开发人员不友好。
(2)关于date类型的说明。
解释:
date类型通过JSON数据传输时是字符串类型。它的由来是,首先服务器用date类型表示时间类,时间类中包含着很多的信息,需要通过dateFormat时间表述格式转换成字符串类型返回。JSON转换成字典的时候,date在字典中是NSString类型,iOS端需要还原它的本来面目。但是在转换成NSDate的使用需要知道之前date转string的时候使用的dateFormat,因此关于dateFormat需要要求服务端开发人员统一规范(比如我们公司使用的是"YYYY-MM-dd HH:mm:ss")。
在开发过程中容易在date这块出现模糊出现动摇,比如产品上的要求是将两个时间合并在一起显示(2018年10月10日 6:00 - 18:00),这种情境下服务端是将两个date字段返回呢、还是将显示的内容拼接好之后使用string字段返回呢?其实,原则很简单:服务器返回数据到客户端的目的无非就是两个,第一个目的就是为了显示,另一个目的就是为了客户端做逻辑判断。在这里,如果客户端不需要使用“开始时间”或者“结束时间”做业务处理,那么就让服务端做好拼装用string返回,客户端拿到这个数据之间显示。相反,如果客户端需要使用“开始时间”或者“结束时间”做逻辑判断,那么就用两个date字段返回,拼接显示的事情交给客户端处理。
关于时间信息采用什么数据类型,另一种方案就是全部使用时间戳,采用integer类型返回。两种方案都可以,统一好就行。
(3)关于Enum类型的说明。
解释:enum类型本质上就是int类型。为了体现枚举字段的枚举性质,iOS端需要在模型上创建一个同样的枚举类型。这一点无需置疑,但是在实际的项目开发中依然会出现一些摇摆不定的方案。以下举例一起摇摆不定的例子,后面会给出一些建议方案:
比如,订单状态这个字段。
之前接口中使用的是枚举字段,iOS端通过enum定义枚举类型。
后面产品上的设计需要将订单状态对应的文本(比如1-“未支付”、2-“已支付”等)显示在界面中。iOS采用的是本地硬编码的方式,将枚举值与文本对应起来。
但是当产品上的设计需要将“已支付”改成“完成支付”显示的时候,硬编码肯定是不行的。所以接口中增加一个订单状态的string类型用来显示其对应的文本内容。
再后来,服务端同学觉得两个字段可以合并为一个对象模型(keyValueModel类,属性key:int,属性value:string),至于枚举的种类,在字段的说明区域显示。
使用keyValueModel类一段时间后发现,枚举的范围增加后,服务端同学容易忘记在字段的说明区域编辑了,或者是枚举值十多种之后,显示不下(显示不雅观)。
其实这个问题很好解决,还是使用上面提到的原则。使用两个字段,枚举字段用来供客户端的同学做逻辑判断、string字段用来供客户端的同学做界面展示。
四、总结
根据“服务器返回数据到客户端的目的无非就是两个,第一个目的就是为了显示,另一个目的就是为了客户端做逻辑判断”的原则,结合产品的设计需求,作出统一化的处理。