Skip to content

KeyPath support for Codable types in Swift via extensions.

License

Notifications You must be signed in to change notification settings

andreybog/CodableKeyPath

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 

Repository files navigation

CodableKeyPath

KeyPath support for Codable types in Swift via extensions.

Assume we have json:

{
    "id": 1,
    "name": "Tomas",
    "meta_info": {
        "player_id": 1,
        "link": "http://profile.com.ua",
        "avatar": {
            "id": 1,
            "url": "http://someimage.jpg"
        }
    }
}

and Person struct:

struct Person {
    let id: Int
    let name: String
    var avatarURL: URL?
    var avatarId: Int?
}

Decoding

We can decode json in Person by adding follow extensions:

extension Person {
    private enum CodingKeys: String, CodingKey {
        case id
        case name
        case avatar
        case url
        case metaInfo = "meta_info"
    }
}

extension Person: Decodable {
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
    
        id = try container.decode(.id)
        name = try container.decode(.name)
        
        avatarURL = try container.decodeIfPresent([.metaInfo, .avatar, .url])
        avatarId = try container.decodeIfPresent([.metaInfo, .avatar, .id])
    }
}


let json: Data = "mentioned above json string".data(using: .utf8)
let decoder = JSONDecoder()
let person = try decoder.decode(Person.self, from: json)

Encoding

Encoding process the same:

extension Person: Encodable {
    func encode(to encoder: Encoder) throws {
        var containers: [String: KeyedEncodingContainer<Person.CodingKeys>] = [:]
        var container = encoder.container(keyedBy: CodingKeys.self)
        
        try container.encode(id, forKey: .id)
        try container.encode(name, forKey: .name)
        
        try container.encode(avatarId, keyPath: [.metaInfo, .avatar, .id], containers: &containers)
        try container.encode(avatarURL, keyPath: [.metaInfo, .avatar, .url], containers: &containers)
    }
}

let encoder = JSONEncoder()
let personData = try encoder.encoder(person)

About

KeyPath support for Codable types in Swift via extensions.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages