Search code examples
swiftkotlinalamofirecombinedecodable

Set an Alter name for property in Decodable class | Swift


I'm developing an existing Android Kotlin app for IOS Swift UI.

In Kotlin when using Gson, I had a Client model class:

abstract class Client(
        @SerializedName("nombre")
        var name: String? = null,
        @SerializedName(value="cliente_id", alternate = ["id"])
        var client_id: Int = -1,
)

As you can see, I use @SerializedName() to give Client property name or client_id an alter name. I do this because when I get the data from the API, Client Json has "nombre" and not "name" as I want. So @SerializedName() makes possible to detect "nombre" in JSON as "name" or detect "cliente_id" as "client_id" in Kotlin model Classes. This way I can read data from API using my own property names.

Well, now I'm facing the same issue in Swift. I want to use my own property names and not the API JSON property names.

My swift Client model class looks like this:

class Client: Identifiable, Decodable{
    
    init(id: Int, token: String) {
        self.cliente_id = id
        self.token = token
    }
    
    let cliente_id: Int
    let token: String
}

And I get client data from API like this:

let request = AF.request(
    url, method: .post,
    parameters: parameters,
    encoder: JSONParameterEncoder.default
)

request.validate(statusCode: 200...299)
request.responseDecodable(of: Client.self) { response in
    if let loginResponse = response.value{//Success
        loginPublisher.send(loginResponse)
    }
    else{//Failure
        loginPublisher.send(completion: Subscribers.Completion<NetworkError>.failure(.thingsJustHappen))
    }
}

In order to be able to use Client a decodable, Client has to implement Decodable. Well, all I want is Client to has id and not cliente_id as a property name.

Something like

class Client: Identifiable, Decodable{

    init(id: Int, token: String) {
        self.id = id
        self.token = token
    }

    @NameforDecode("cliente_id")
    let id: Int
    let token: String
}

Is this possible?


Solution

  • In Swift you achieve this by giving your type custom CodingKeys:

    extension Client: Decodable {
    
        enum CodingKeys: String, CodingKey {
            case id = "cliente_id"
            case token
        }
    }
    

    Enum cases have to correspond to your properties; the raw value can be declared as a String if the keys in the JSON don't match your property names. There's more information in the Encoding and Decoding Custom Types developer article.