An extension for Alamofire that converts JSON data into Decodable objects.

Overview

CodableAlamofire

Build Status Swift 5.x SPM compatible Carthage Compatible Version platforms

Swift 4 introduces a new Codable protocol that lets you serialize and deserialize custom data types without writing any special code and without having to worry about losing your value types. 🎉

Awesome, isn't it? And this library helps you write less code! It's an extension for Alamofire that converts JSON data into Decodable object.

Useful Resources:

Usage

Let's decode a simple json file:

{
    "result": {
        "libraries": [
            {
                "name": "Alamofire",
                "stars": 23857,
                "url": "https://github.com/Alamofire/Alamofire",
                "random_date_commit": 1489276800
            },
            {
                "name": "RxSwift",
                "stars": 9600,
                "url": "https://github.com/ReactiveX/RxSwift",
                "random_date_commit": 1494547200
            }	
        ]
    }
}

with the following Swift model:

private struct Repo: Decodable {
    let name: String
    let stars: Int
    let url: URL
    let randomDateCommit: Date
    
    private enum CodingKeys: String, CodingKey {
        case name
        case stars
        case url
        case randomDateCommit = "random_date_commit"
    }
}

There is a similar method to responseData, responseJSON - responseDecodableObject:

func responseDecodableObject<T: Decodable>(queue: DispatchQueue? = nil, keyPath: String? = nil, decoder: JSONDecoder = JSONDecoder(), completionHandler: @escaping (AFDataResponse<T>) -> Void)
  • queue - The queue on which the completion handler is dispatched.
  • keyPath - The keyPath where object decoding should be performed.
  • decoder - The decoder that performs the decoding of JSON into semantic Decodable type.
let url = URL(string: "https://raw.githubusercontent.com/otbivnoe/CodableAlamofire/master/keypathArray.json")!
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .secondsSince1970 // It is necessary for correct decoding. Timestamp -> Date.

AF.request(url).responseDecodableObject(keyPath: "result.libraries", decoder: decoder) { (response: AFDataResponse<[Repo]>) in
    let repo = response.value
    print(repo)
}

Note:

  • For array: DataResponse<[Repo]>
  • For single object: DataResponse<Repo>

Requirements

  • Swift 4+
  • Xcode 9+

Installation 🔥

CocoaPods

CocoaPods is a dependency manager for Swift and Objective-C Cocoa projects. It has over eighteen thousand libraries and can help you scale your projects elegantly. You can install it with the following command:

$ sudo gem install cocoapods

To integrate CodableAlamofire, simply add the following line to your Podfile:

target 'Test' do
  use_frameworks!

  pod 'CodableAlamofire'
  
end

Carthage

Carthage is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.

You can install Carthage with Homebrew using the following command:

$ brew update
$ brew install carthage

To integrate CodableAlamofire into your Xcode project using Carthage, specify it in your Cartfile:

github "Otbivnoe/CodableAlamofire"

Run carthage update to build the framework and drag the built CodableAlamofire.framework into your Xcode project.

Comments
  • keyPath performance issues

    keyPath performance issues

    Really handy library, thanks for making it.

    I'm wondering if you think the responseDecodableObject[keyPath: ...] is a good call. There's going to be performance hit deserializing to json then serializing back to data then deserializing to codable object.

    Users might not look under the hood and see this. Isn't better they just make a container object or writing a customer coder method? Also asking for myself really.

    Best,

    enhancement 
    opened by sameerjj 3
  • Cannot convert value of type 'HTTPHeaders' (aka 'Dictionary<String, String>') to expected argument type 'DispatchQueue?

    Cannot convert value of type 'HTTPHeaders' (aka 'Dictionary') to expected argument type 'DispatchQueue?

        var id:        String
        var owner_id:  String
        var name:      String
        var active:    Bool?
        var share:     Bool?
        var date:      Int?
        var duration:  Int
        
        typealias DownloadComplete = () -> ()
    }
    
    extension ActiveChannelHangouts {
        static func from(json: String, using encoding: String.Encoding = .utf8) -> ActiveChannelHangouts? {
            guard let data = json.data(using: encoding) else { return nil }
            return ActiveChannelHangouts.from(data: data)
        }
        
        static func from(data: Data) -> ActiveChannelHangouts? {
            let decoder = JSONDecoder()
            do {
                return try decoder.decode(ActiveChannelHangouts.self, from: data)
            } catch  {
                print(error.localizedDescription)
                return nil
            }
        }
        
        var jsonData: Data? {
            let encoder = JSONEncoder()
            do {
                return try encoder.encode(self)
            } catch {
                print(error.localizedDescription)
                return nil
            }
        }
        
        var jsonString: String? {
            guard let data = self.jsonData else { return nil }
            return String(data: data, encoding: .utf8)
        }
        
    }
    
    extension ActiveChannelHangouts {
        enum CodingKeys: String, CodingKey {
            case id       = "id"
            case ownerId  = "ownerId"
            case name     = "name"
            case active   = "active"
            case share    = "share"
            case date     = "date"
            case duration = "duration"
        }
    }
    
    // from my APIClient struct trying to call this method 
    func responseDecodableObject<T: Decodable>(url: String, queue: DispatchQueue? = nil,
                                                   keyPath: String? = nil,
                                                   decoder: JSONDecoder = JSONDecoder(),
                                                   completionHandler: @escaping (DataResponse<T>) -> Void) {
            if !PerfectLocalAuth.sessionid.isEmpty {
                Alamofire.request(url).responseDecodableObject(queue: PerfectLocalAuth.setHeaders(), keyPath: keyPath, decoder: decoder) {
                    (response: DataResponse<[T]>) in
                    let repo = response.result.value
                    print(repo)
                }
                
            }
        }
    

    i am trying to create one func that can be handle for all my fetch request but i go this error Cannot convert value of type 'HTTPHeaders' (aka 'Dictionary<String, String>') to expected argument type 'DispatchQueue?

    help wanted question 
    opened by saroar 3
  • `GenericCache(0x1016d3d40): cyclic metadata dependency detected, aborting` when work with generic decodable type

    `GenericCache(0x1016d3d40): cyclic metadata dependency detected, aborting` when work with generic decodable type

    Swift 4 & Xcode 9.0 on mac OS High Sierra

    Where the issue accurs:

    ...alamofireRequest.responseDecodableObject(
        queue: nil, 
        keyPath: nil, 
        decoder: JSONDecoder()) { 
            (resp: DataResponse<GenralResponse<FlexibleValue>>) in
            logger.verbose(resp)
    }
    

    Related Types

    // FlexibleValue is for decoding the flexible part of response JSON.

    struct FlexibleValue: Decodable {
        var role: [String]
    }
    

    // GeneralResponse<T> is the designed to decode general response from back-end, with a hosted type T, which is decodable too.

    struct GeneralResponse<T: Decodable>: Decodable  {
        struct Head: Decodable {
            let version: String
            let msgtype: String
            let interface: String
            let remark: String
        }
        struct Body: Decodable {
            let ret: String
            let retcode: String
            let retinfo: String
            let data: T?
        }
        let head: Head
        let body: Body
    }
    
    opened by benjamin-wen 3
  • Dependency Specification prevents Updates

    Dependency Specification prevents Updates

    The Alamofire dependency is specified in such a manner that users of this pod are locked to a specific minor version. As Alamofire follows sematic versioning (see Alamofire/Changelog), locking this dependency to a major version is all that should be required.

    Is it possible for

    s.dependency 'Alamofire', '~> 5.0.0-rc.3'
    

    to be replaced with

    s.dependency 'Alamofire', '~> 5.0'
    
    opened by michaeldclifford 2
  • Alamofire 5 compatibiliy

    Alamofire 5 compatibiliy

    Hello,

    First of all thanks for such useful library.

    It seems Alamofire 5.0.0-rc.3 is API stable now. Is there a way/branch to use that with CodableAlamofire? without forking?

    Best

    enhancement 
    opened by ergunkocak 2
  • Add platform specifications to Package

    Add platform specifications to Package

    This PR updates the Package.swift tool version and adds platform information.

    This makes it possible to use CodableAlamofire with Alamofire 4.9 using Swift Package Manager.

    opened by danielsaidi 2
  • JSON property sometimes is a numeric value and sometimes a string value

    JSON property sometimes is a numeric value and sometimes a string value

    Hi,

    I have a special case, I have a JSON response which sometimes returns a numeric value and sometimes a string value for the same key. Is there any way to handle such a JSON response.

    I know, that this isn't a good idea in general, but I don't have access to the server backend 😉.

    question 
    opened by patricks 2
  • Alamofire 4.x and RxSwift 6 Support

    Alamofire 4.x and RxSwift 6 Support

    Moving to Alamofire 5.x isn't possible for us at the moment but we would like to be one RxSwift 6.2 for other reasons.

    This is branched off the last Alamofire 4.x release as far as I can tell but github won't accept a pr against it for some reason.

    I'll appreciate if this is no longer part of this repo and maintain my own fork until we can get Alamofire upgraded.

    opened by foxware00 1
  • JSONDecoder.dateDecodingStrategy not working for custom format

    JSONDecoder.dateDecodingStrategy not working for custom format

    When using this DateFormatter separately, I can successfully deserialize date string with it:

    extension DateFormatter {
        static let apiDateFormatter: DateFormatter = {
            let formatter = DateFormatter()
            //2019-08-05T08:41:06.590Z
            formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
            return formatter
        }()
    }
    

    If I use the same formatter when calling .responeDecodableObject(decoder: decoder), model properties (of Date type) are set to nil.

    let decoder = JSONDecoder()
    decoder.dateDecodingStrategy = .formatted(.apiDateFormatter)
    
    Alamofire.request(url, method: method, parameters: parameters, encoding: encoding, headers: headers)
        .responseDecodableObject(decoder: decoder) { (response: DataResponse<T>) in
            let data = response.data
    }
    

    Is there any more setup that I am not aware of? Thanks

    opened by Dino4674 1
Releases(1.2.1)
Owner
Nikita Ermolenko
iOS evangelist | lover of music, bikes and photography | ex-Yandex
Nikita Ermolenko
JSONHelper - ✌ Convert anything into anything in one operation; JSON data into class instances, hex strings into UIColor/NSColor, y/n strings to booleans, arrays and dictionaries of these; anything you can make sense of!

JSONHelper Convert anything into anything in one operation; hex strings into UIColor/NSColor, JSON strings into class instances, y/n strings to boolea

Baris Sencan 788 Jul 19, 2022
Encode and decode deeply-nested data into flat Swift objects

DeepCodable: Encode and decode deeply-nested data into flat Swift objects Have you ever gotten a response from an API that looked like this and wanted

Mike Lewis 91 Dec 26, 2022
Decodable Simple and strict, yet powerful object mapping made possible by Swift 2's error handling.

Decodable Simple and strict, yet powerful object mapping made possible by Swift 2's error handling. Greatly inspired by Argo, but without a bizillion

Johannes Lund 1k Jul 15, 2022
Reflection based (Dictionary, CKRecord, NSManagedObject, Realm, JSON and XML) object mapping with extensions for Alamofire and Moya with RxSwift or ReactiveSwift

EVReflection General information At this moment the master branch is tested with Swift 4.2 and 5.0 beta If you want to continue using EVReflection in

Edwin Vermeer 964 Dec 14, 2022
HandyJSON is a framework written in Swift which to make converting model objects to and from JSON easy on iOS.

HandyJSON To deal with crash on iOS 14 beta4 please try version 5.0.3-beta HandyJSON is a framework written in Swift which to make converting model ob

Alibaba 4.1k Dec 29, 2022
ObjectMapper is a framework written in Swift that makes it easy for you to convert your model objects to and from JSON.

ObjectMapper is a framework written in Swift that makes it easy for you to convert your model objects (classes and structs) to and from J

Tristan Himmelman 9k Jan 2, 2023
JSONExport is a desktop application for Mac OS X which enables you to export JSON objects as model classes with their associated constructors, utility methods, setters and getters in your favorite language.

JSONExport JSONExport is a desktop application for Mac OS X written in Swift. Using JSONExport you will be able to: Convert any valid JSON object to a

Ahmed Ali 4.7k Dec 30, 2022
JSONJoy - Convert JSON to Swift objects

JSONJoy Convert JSON to Swift objects. The Objective-C counterpart can be found here: JSONJoy. Parsing JSON in Swift has be likened to a trip through

Dalton 350 Oct 15, 2022
Magical Data Modeling Framework for JSON - allows rapid creation of smart data models. You can use it in your iOS, macOS, watchOS and tvOS apps.

JSONModel - Magical Data Modeling Framework for JSON JSONModel allows rapid creation of smart data models. You can use it in your iOS, macOS, watchOS

JSONModel 6.9k Dec 8, 2022
Magical Data Modeling Framework for JSON - allows rapid creation of smart data models. You can use it in your iOS, macOS, watchOS and tvOS apps.

JSONModel - Magical Data Modeling Framework for JSON JSONModel allows rapid creation of smart data models. You can use it in your iOS, macOS, watchOS

JSONModel 6.8k Nov 19, 2021
JSONNeverDie - Auto reflection tool from JSON to Model, user friendly JSON encoder / decoder, aims to never die

JSONNeverDie is an auto reflection tool from JSON to Model, a user friendly JSON encoder / decoder, aims to never die. Also JSONNeverDie is a very important part of Pitaya.

John Lui 454 Oct 30, 2022
JSEN (JSON Swift Enum Notation) is a lightweight enum representation of a JSON, written in Swift.

JSEN /ˈdʒeɪsən/ JAY-sən JSEN (JSON Swift Enum Notation) is a lightweight enum representation of a JSON, written in Swift. A JSON, as defined in the EC

Roger Oba 8 Nov 22, 2022
JSON-Practice - JSON Practice With Swift

JSON Practice Vista creada con: Programmatic + AutoLayout Breve explicación de l

Vanesa Giselle Korbenfeld 0 Oct 29, 2021
Ss-json - High-performance json parsing in swift

json 0.1.1 swift-json is a pure-Swift JSON parsing library designed for high-per

kelvin 43 Dec 15, 2022
Swift-json - High-performance json parsing in swift

json 0.1.4 swift-json is a pure-Swift JSON parsing library designed for high-per

kelvin 43 Dec 15, 2022
Swift parser for JSON Feed — a new format similar to RSS and Atom but in JSON.

JSONFeed Swift parser for JSON Feed — a new format similar to RSS and Atom but in JSON. For more information about this new feed format visit: https:/

Toto Tvalavadze 31 Nov 22, 2021
Codable code is a Swift Package that allows you to convert JSON Strings into Swift structs

Codable code is a Swift Package that allows you to convert JSON Strings into Swift structs.

Julio Cesar Guzman Villanueva 2 Oct 6, 2022
A tiny Safari Web Extension for presenting highlighted JSON files

A tiny Safari Web Extension for presenting highlighted JSON files

Lex Tang 31 Sep 9, 2022
SwiftyJSON makes it easy to deal with JSON data in Swift.

SwiftyJSON SwiftyJSON makes it easy to deal with JSON data in Swift. Platform Build Status *OS Linux Why is the typical JSON handling in Swift NOT goo

SwiftyJSON 21.7k Jan 3, 2023