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 · Dec 25, 2016 · 5775 views
    This topic created in 3429 days ago, the information mentioned may be changed or developed.

    背景

    之前介绍的模型字段生成代码中, 我们默认生成了 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 replies    2017-11-27 17:11:09 +08:00
    janita
        1
    janita  
       Dec 25, 2016 via iPhone
    用在什么地方呢?
    banxi1988
        2
    banxi1988  
    OP
       Dec 26, 2016
    @janita 用在你的 Model 上.
    04BxPLXu2M6UKH6Z
        3
    04BxPLXu2M6UKH6Z  
       Jan 9, 2017
    POP 大法好
    HHHH
        4
    HHHH  
       Nov 27, 2017
    py 大法好~~
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2881 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 43ms · UTC 10:19 · PVG 18:19 · LAX 03:19 · JFK 06:19
    ♥ Do have faith in what you're doing.