How do I use custom keys with Swift 4's Decodable protocol?

前端 未结 4 909
面向向阳花
面向向阳花 2020-11-22 14:57

Swift 4 introduced support for native JSON encoding and decoding via the Decodable protocol. How do I use custom keys for this?

E.g., say I have a struct

<         


        
4条回答
  •  轮回少年
    2020-11-22 15:46

    What I have done is create own structure just like what you are getting from the JSON with respect to its data types.

    Just like this:

    struct Track {
    let id : Int
    let contributingArtistNames:String
    let name : String
    let albumName :String
    let copyrightP:String
    let copyrightC:String
    let playlistCount:Int
    let trackPopularity:Int
    let playlistFollowerCount:Int
    let artistFollowerCount : Int
    let label : String
    }
    

    After this you need to create an extension of the same struct extending decodable and the enum of the same structure with CodingKey and then you need to initialize the decoder using this enum with its keys and datatypes (Keys will come from the enum and the datatypes will be coming or say referenced from the structure itself)

    extension Track: Decodable {
    
        enum TrackCodingKeys: String, CodingKey {
            case id = "id"
            case contributingArtistNames = "primaryArtistsNames"
            case spotifyId = "spotifyId"
            case name = "name"
            case albumName = "albumName"
            case albumImageUrl = "albumImageUrl"
            case copyrightP = "copyrightP"
            case copyrightC = "copyrightC"
            case playlistCount = "playlistCount"
            case trackPopularity = "trackPopularity"
            case playlistFollowerCount = "playlistFollowerCount"
            case artistFollowerCount = "artistFollowers"
            case label = "label"
        }
        init(from decoder: Decoder) throws {
            let trackContainer = try decoder.container(keyedBy: TrackCodingKeys.self)
            if trackContainer.contains(.id){
                id = try trackContainer.decode(Int.self, forKey: .id)
            }else{
                id = 0
            }
            if trackContainer.contains(.contributingArtistNames){
                contributingArtistNames = try trackContainer.decode(String.self, forKey: .contributingArtistNames)
            }else{
                contributingArtistNames = ""
            }
            if trackContainer.contains(.spotifyId){
                spotifyId = try trackContainer.decode(String.self, forKey: .spotifyId)
            }else{
                spotifyId = ""
            }
            if trackContainer.contains(.name){
                name = try trackContainer.decode(String.self, forKey: .name)
            }else{
                name = ""
            }
            if trackContainer.contains(.albumName){
                albumName = try trackContainer.decode(String.self, forKey: .albumName)
            }else{
                albumName = ""
            }
            if trackContainer.contains(.albumImageUrl){
                albumImageUrl = try trackContainer.decode(String.self, forKey: .albumImageUrl)
            }else{
                albumImageUrl = ""
            }
            if trackContainer.contains(.copyrightP){
                copyrightP = try trackContainer.decode(String.self, forKey: .copyrightP)
            }else{
                copyrightP = ""
            }
            if trackContainer.contains(.copyrightC){
                    copyrightC = try trackContainer.decode(String.self, forKey: .copyrightC)
            }else{
                copyrightC = ""
            }
            if trackContainer.contains(.playlistCount){
                playlistCount = try trackContainer.decode(Int.self, forKey: .playlistCount)
            }else{
                playlistCount = 0
            }
    
            if trackContainer.contains(.trackPopularity){
                trackPopularity = try trackContainer.decode(Int.self, forKey: .trackPopularity)
            }else{
                trackPopularity = 0
            }
            if trackContainer.contains(.playlistFollowerCount){
                playlistFollowerCount = try trackContainer.decode(Int.self, forKey: .playlistFollowerCount)
            }else{
                playlistFollowerCount = 0
            }
    
            if trackContainer.contains(.artistFollowerCount){
                artistFollowerCount = try trackContainer.decode(Int.self, forKey: .artistFollowerCount)
            }else{
                artistFollowerCount = 0
            }
            if trackContainer.contains(.label){
                label = try trackContainer.decode(String.self, forKey: .label)
            }else{
                label = ""
            }
        }
    }
    

    You need to change here each and every key and datatypes according to your needs and use it with the decoder.

提交回复
热议问题