JSON Parsing With Codable

AlamofireCodable: An extension to Alamofire which automatically converts JSON response data into swift objects using Codable.
This project is heavily inspired by the popular AlamofireObjectMapper.

image.png

Installation

AlamofireCodable can be added to your project using CocoaPods by adding the following line to your Podfile:

pod 'AlamofireCodable'

Example

To run the example project, clone the repo, and run pod install from the Example directory first.

Requirements

Xcode 9+ , Swift 4+

Usage

Given a URL which returns weather data in the following form:

{  
   "data":{  
      "location":"Toronto, Canada",
      "three_day_forecast":[  
         {  
            "conditions":"Partly cloudy",
            "day":"Monday",
            "temperature":20
         },
         {  
            "conditions":"Showers",
            "day":"Tuesday",
            "temperature":22
         },
         {  
            "conditions":"Sunny",
            "day":"Wednesday",
            "temperature":28
         }
      ]
   }
}

You can use the extension as the follows:

import AlamofireCodable

        let form = WeatherForm()
        Alamofire.request(
                form.url,
                method: HTTPMethod.get,
                parameters: form.parameters(),
                encoding: form.encoding(),
                headers: form.headers()
            )
            .responseObject(keyPath: "data",completionHandler: { (response: DataResponse<Weather>) in
                switch response.result {
                case .success(let object):
                    debugPrint("🌹", object.location)
                case .failure(let error):
                    debugPrint("🌹", error.localizedDescription)
                }
            })

The Weather object in the completion handler is a custom object which you define. The only requirement is that the object must conform to Codable protocol. In the above example, the Weather object looks like the following:

{  
   "data":{  
      "location":"Toronto, Canada",
      "three_day_forecast":[  
         {  
            "conditions":"Partly cloudy",
            "day":"Monday",
            "temperature":20
         },
         {  
            "conditions":"Showers",
            "day":"Tuesday",
            "temperature":22
         },
         {  
            "conditions":"Sunny",
            "day":"Wednesday",
            "temperature":28
         }
      ]
   }
}

The extension uses Generics to allow you to create your own custom response objects. Below is the responseObject function definition. Just replace T in the completionHandler with your custom response object and the extension handles the rest:

public func responseObject<T: Codable>(queue: DispatchQueue? = nil, keyPath: String? = nil,  completionHandler: @escaping (DataResponse<T>) -> Void) -> Self 

The responseObject function has 2 optional parameters and a required completionHandler:

  • queue: The queue on which the completion handler is dispatched.
  • keyPath: The key path of the JSON where object mapping should be performed
  • completionHandler: A closure to be executed once the request has finished and the data has been decoded by JSONDecoder.

Easy decode of Nested Objects

AlamofireCodable supports dot notation within keys for easy mapping of nested objects. Given the following JSON String:

{  
   "data":{  
      "location":"Toronto, Canada",
      "three_day_forecast":[  
         {  
            "conditions":"Partly cloudy",
            "day":"Monday",
            "temperature":20
         },
         {  
            "conditions":"Showers",
            "day":"Tuesday",
            "temperature":22
         },
         {  
            "conditions":"Sunny",
            "day":"Wednesday",
            "temperature":28
         }
      ]
   }
}

You can access the nested objects as follows:

      let form = WeatherForm()
        Alamofire.request(
            form.url,
            method: HTTPMethod.get,
            parameters: form.parameters(),
            encoding: form.encoding(),
            headers: form.headers()
            )
            .responseObject(completionHandler: { (response: DataResponse<RootModel>) in
                switch response.result {
                case .success(let root):
                    debugPrint("🌹", root)
                case .failure(let error):
                    debugPrint("🌹", error.localizedDescription)
                }
            })

KeyPath

The keyPath variable is used to drill down into a JSON response and only map the data found at that keyPath. It supports nested values such as data.three_day_forecast to drill down several levels in a JSON response.

let form = WeatherForm()
        Alamofire.request(
                form.url,
                method: HTTPMethod.get,
                parameters: form.parameters(),
                encoding: form.encoding(),
                headers: form.headers()
            )
            .responseArray(keyPath: "data.three_day_forecast", completionHandler: { (response: DataResponse<[Forecast]>) in
                switch response.result {
                case .success(let array):
                    debugPrint("🌹", array)
                case .failure(let error):
                    debugPrint("🌹", error.localizedDescription)
                }
            })

Array Responses

If you have an endpoint that returns data in Array form you can map it with the following function:

public func responseArray<T: Codable>(queue: DispatchQueue? = nil, keyPath: String? = nil, completionHandler: @escaping (DataResponse<[T]>) -> Void) -> Self 

For example, if your endpoint returns the following:

[
    { 
        "conditions": "Partly cloudy",
        "day" : "Monday",
        "temperature": 20 
    },
    { 
        "conditions": "Showers",
        "day" : "Tuesday",
        "temperature": 22 
    },
    { 
        "conditions": "Sunny",
        "day" : "Wednesday",
        "temperature": 28 
    }
]

You can request and map it as follows:

        let form = WeatherForm()
        Alamofire.request(
                form.url,
                method: HTTPMethod.get,
                parameters: form.parameters(),
                encoding: form.encoding(),
                headers: form.headers()
            )
            .responseArray(keyPath: "data.three_day_forecast", completionHandler: { (response: DataResponse<[Forecast]>) in
                switch response.result {
                case .success(let array):
                    debugPrint("🌹", array)
                case .failure(let error):
                    debugPrint("🌹", error.localizedDescription)
                }
            })

Author

wangchengqvan@gmail.com, chengquan.wang@ele.me

License

AlamofireCodable is available under the MIT license. See the LICENSE file for more info.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • **2014真题Directions:Read the following text. Choose the be...
    又是夜半惊坐起阅读 9,934评论 0 23
  • 鸡汤是什么,就是微暖你内心的东西,可以是一句话也可以是一个东西,只要温暖你的心,那就是鸡汤。 知乎上很流行反向思维...
    西边秋阅读 197评论 0 1
  • 泗城门前。 风呼啸而过,一把烈火就着满地残骸蔓延开来。朦胧间,黑夜竟被映得白昼一般。只是天边的艳色云朵燃烧似的...
    蓝冰红焰阅读 268评论 0 0
  • 经过两个月的阅读,发现并没有提前计划周密的书单,读起来感觉没方向,所以打算从3月份开始,改变读书策略。从原来杂乱无...
    诗云Monica阅读 257评论 1 4