V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
iOS 开发实用技术导航
NSHipster 中文版
http://nshipster.cn/
cocos2d 开源 2D 游戏引擎
http://www.cocos2d-iphone.org/
CocoaPods
http://cocoapods.org/
Google Analytics for Mobile 统计解决方案
http://code.google.com/mobile/analytics/
WWDC
https://developer.apple.com/wwdc/
Design Guides and Resources
https://developer.apple.com/design/
Transcripts of WWDC sessions
http://asciiwwdc.com
Cocoa with Love
http://cocoawithlove.com/
Cocoa Dev Central
http://cocoadevcentral.com/
NSHipster
http://nshipster.com/
Style Guides
Google Objective-C Style Guide
NYTimes Objective-C Style Guide
Useful Tools and Services
Charles Web Debugging Proxy
Smore
banxi1988
V2EX  ›  iDev

[Swift] 从 JSON 到 Model: 协议默认方法让生活更简单

  •  
  •   banxi1988 ·
    banxi1988 · 2016-12-25 14:51:28 +08:00 · 5017 次点击
    这是一个创建于 2892 天前的主题,其中的信息可能已经有所发展或是发生改变。

    背景

    之前介绍的模型字段生成代码中, 我们默认生成了 init(json:JSON) 方法. 假设就是如下的 User Model

    struct User{
      let name:String
      let age:Int
      init(json: JSON) {
        self.name = json["name"].stringValue
        self.age = json["age"].intValue
      }
    }
    

    开发中我们经常需要得到的是 一个 User 数组.

    完善之路

    1. 也许我们会写如下的方法:
    func parseUsers(from data:JSON) -> [User]{
      var array:[User] = []
      for (index,json) in data{
      		array.append(User(json:json))
      }
      return array
    }
    
    1. 上面的代码,对于 Swift 来说, 还有很大的改进空间. 首先. 我们可以简化成一行代码, 如下:
    func parseUsers(from data:JSON) -> [User]{
      return data.map{ User(json:$0.1) }
    }
    

    够简单了吧. 使用 map 方法. 一行就 OK 了. 简单明了. 但是

    终极简化

    在 Swift 中我们可以一行代码都不写.就实现上面的功能. 怎么实现? 答案就在神奇的默认协议实现方法上.

    1. 我们对 Model 类提取一个协议出来 如下: 很简单,就是指定模型类可以从 JSON 反序列化成 Model.
    public protocol JSONDeserializable {
      init(json:JSON)
    }
    
    1. 声明 User 实现了 上面的协议.
    extension User:JSONDeserializable{ 
    }
    

    因为我们实际上已经实现了. 所以我们不要额外写代码了.

    1. JSONDeserializable 添加一个默认协议静态方法. 用来将 JSON 数组转换成 Model 数组. 如下.
    extension JSONDeserializable{
      public static func objects(from json: JSON) -> [Self]{
        return json.map{ Self(json:$0.1) }
      }
    }
    

    OK 大功告成!. 现在反序列化一个 User 数组的 json 只需要这样写就可以了.

      let users = User.objects(from: json)
    

    更重要 的是,所以其他的 Model 类型,只要添加实现 JSONDeserializable 的声明就拥有了从 JSON 数组反序列化的能力了.

    总结

    至此,整个从 API 到 Model 的流程都变得无比简单,及别人愉快.

    1. 使用 generate_model 服务将 从 API 的 JSON 返回转化成 Model 的声明. (生成的代码中的 BXModel 协议,继承声明了 JSONDeserializable)

    2. 借助 Swift 默认协议. 简化 Model 数组的反序列化.

    开源:从 API 到 Model 的代码生成脚本 Generate Model Code from JSON API Response

    4 条回复    2017-11-27 17:11:09 +08:00
    janita
        1
    janita  
       2016-12-25 23:21:28 +08:00 via iPhone
    用在什么地方呢?
    banxi1988
        2
    banxi1988  
    OP
       2016-12-26 08:50:20 +08:00
    @janita 用在你的 Model 上.
    Tangdixi
        3
    Tangdixi  
       2017-01-09 23:40:36 +08:00
    POP 大法好
    HHHH
        4
    HHHH  
       2017-11-27 17:11:09 +08:00
    py 大法好~~
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1042 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 20:14 · PVG 04:14 · LAX 12:14 · JFK 15:14
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.