MoreCodable expands the possibilities of `Codable`.
Switch branches/tags
Clone or download
Latest commit b7b691d Dec 11, 2018
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
MoreCodable.xcodeproj Update Swift to Swift 4.2 Sep 20, 2018
Sources Clean code Dec 11, 2018
Tests Clean code Dec 11, 2018
.gitignore Add Package.swift Dec 7, 2018
.swift-version Update .swift-version Sep 20, 2018
.travis.yml Update CI Sep 20, 2018
LICENSE Initial commit Mar 1, 2018
MoreCodable.podspec Merge pull request #6 from tattn/swift4.2 Sep 20, 2018
Package.swift Add Package.swift Dec 7, 2018
README.md Update README.md Mar 9, 2018

README.md

MoreCodable

MoreCodable expands the possibilities of "Codable".

Installation

Carthage

github "tattn/MoreCodable"

CocoaPods

pod 'MoreCodable'

Feature

DictionaryEncoder / DictionaryDecoder

struct User: Codable {
    let id: Int
    let name: String
}

let encoder = DictionaryEncoder()
let user = User(id: 123, name: "tattn")
let dictionary: [String: Any] = try! encoder.encode(user) // => {"id": 123, "name": "tattn"}
let decoder = DictionaryDecoder()
let user = try decoder.decode(User.self, from: dictionary)

URLQueryItemsEncoder / URLQueryItemsDecoder

struct Parameter: Codable {
    let query: String
    let offset: Int
    let limit: Int
}
let parameter = Parameter(query: "ねこ", offset: 10, limit: 20)
let encoder = URLQueryItemsEncoder()
let params: [URLQueryItem] = try! encoder.encode(parameter)

var components = URLComponents(string: "https://example.com")
components?.queryItems = params
components?.url // https://example.com?query=%E3%81%AD%E3%81%93&offset=10&limit=20
let decoder = URLQueryItemsDecoder()
let parameter = try decoder.decode(Parameter.self, from: params)

ObjectMerger

struct APIResponse: Encodable {
    let id: Int
    let title: String
    let foo: String
}

struct APIResponse2: Encodable {
    let tags: [String]
}

struct Model: Decodable {
    let id: Int
    let title: String
    let tags: [String]
}

let response = APIResponse(id: 0, title: "Awesome article", foo: "bar")
let response2 = APIResponse2(tags: ["swift", "ios", "macos"])
let model = try ObjectMerger().merge(Model.self, response, response2)

// success
XCTAssertEqual(model.id, response.id)
XCTAssertEqual(model.title, response.title)
XCTAssertEqual(model.tags, response2.tags)

RuleBasedCodingKey

struct User: Codable {
    let userId: String
    let name: String

    enum CodingKeys: String, RuleBasedCodingKey {
        case userId
        case name

        func codingKeyRule(key: String) -> String {
            return key.uppercased() // custom rule
        }
    }
}

let json = """
{"USERID": "abc", "NAME": "tattn"}
""".data(using: .utf8)!

let user = try! JSONDecoder().decode(User.self, from: json) // => User(userId: "abc", name: "tattn")

SnakeCaseCodingKey

struct User: Codable {
    let userId: String
    let name: String

    enum CodingKeys: String, SnakeCaseCodingKey {
        case userId
        case name
    }
}

let json = """
{"user_id": "abc", "name": "tattn"}
""".data(using: .utf8)!

let user = try! JSONDecoder().decode(User.self, from: json) // ok

UpperCamelCaseCodingKey

struct User: Codable {
    let userId: String
    let name: String

    enum CodingKeys: String, UpperCamelCaseCodingKey {
        case userId
        case name
    }
}

let json = """
{"UserId": "abc", "Name": "tattn"}
""".data(using: .utf8)!

let user = try! JSONDecoder().decode(User.self, from: json) // ok

Failable

let json = """
[
    {"name": "Taro", "age": 20},
    {"name": "Hanako"}
]
""".data(using: .utf8)! // Hanako has no "age"

struct User: Codable {
    let name: String
    let age: Int
}

let users = try! JSONDecoder().decode([Failable<User>].self,
                                      from: json)

// success
XCTAssertEqual(users[0].value?.name, "Taro")
XCTAssertEqual(users[0].value?.age, 20)
XCTAssertNil(users[1].value)

StringTo

let json = """
{
    "int": "100",
    "articleId": "abc"
}
""".data(using: .utf8)!

struct Root: Codable {
    let int: StringTo<Int>
    let articleId: StringTo<ArticleId>

    struct ArticleId: LosslessStringConvertible, Codable {
        var description: String

        init?(_ description: String) {
            self.description = description
        }
    }
}

let root = try! JSONDecoder().decode(Root.self, from: json)

// success
XCTAssertEqual(root.int.value, 100)
XCTAssertEqual(root.articleId.value.description, "abc")

ToDo

  • XMLDecoder/XMLEncoder
  • CSVDecoder/CSVEncoder

Related project

DataConvertible
https://github.com/tattn/DataConvertible

Contributing

  1. Fork it!
  2. Create your feature branch: git checkout -b my-new-feature
  3. Commit your changes: git commit -am 'Add some feature'
  4. Push to the branch: git push origin my-new-feature
  5. Submit a pull request :D

License

MoreCodable is released under the MIT license. See LICENSE for details.