Home > Enterprise >  Why my CustomType cannot conform to Decodable even I conformed it?
Why my CustomType cannot conform to Decodable even I conformed it?

Time:12-12

I have a CustomType that conforms to Decodable, when I want use it as needed value for my function, Xcode complain that CustomType does not conform to Decodable! Should I explicitly make CustomType conformation happen, I also did it, but it did not solved the issue! What I am missing here?

Error:

Type 'CustomType.Type' cannot conform to 'Decodable'

let stringOfJSON: String = """
{ "name": "SwiftPunk", "age": 35 }
"""

let dataOfJSON: Data? = stringOfJSON.data(using: String.Encoding.utf8)

struct CustomType: Decodable {
    
    enum Codingkeys: String, CodingKey {
        case name, age
    }
    
    var name: String
    var age: Int
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: Codingkeys.self)
        name = try container.decode(String.self, forKey: .name)
        age = try container.decode(Int.self, forKey: .age)
    }
    
    
}

func decoderFunction<T: Decodable>(dataOfJSON: Data?, customType: T, decodedValue: (T) -> Void) {
    
    if let unwrappedDataOfJSON: Data = dataOfJSON {
        
        let dataJSONDecoder: JSONDecoder = JSONDecoder()
        
        do {
            let value: T = try dataJSONDecoder.decode(T.self, from: unwrappedDataOfJSON)
            decodedValue(value)
        } catch {
            print("The Data could not be decoded!")
        }
    }
}

use case:

decoderFunction(dataOfJSON: dataOfJSON, customType: CustomType.self, decodedValue: { value in
 
})

CodePudding user response:

The type of the customType parameter is incorrect. It should be the metatype of T (T.Type), not T.

func decoderFunction<T: Decodable>(dataOfJSON: Data?, customType: T.Type, decodedValue: (T) -> Void) {
    ...
}

The method was expecting a value of type T, which should conform to Decodable, but you were giving it a value of type CustomType.Type, which doesn't conform to Decodable (but note that CustomType does).

Also note that you don't need the customType parameter at all. T can be inferred if you specify the type in the closure:

func decoderFunction<T: Decodable>(dataOfJSON: Data?, decodedValue: (T) -> Void) {
    ...
}

decoderFunction(dataOfJSON: dataOfJSON, decodedValue: { (value: CustomType) in
 
})

CodePudding user response:

Change the function signature to:

func decoderFunction<T: Decodable>(
    dataOfJSON: Data?, 
    customType: T.Type, 
    decodedValue: (T) -> Void)

You want to pass in the type of T not a value of T

CodePudding user response:

As you apparently like to annotate types I would omit the type parameter completely and annotate the type in the closure of the caller function.

Further use the Result type to handle a potential error and pass the JSON string to the function rather than optional Data

let stringOfJSON: String = """
{ "name": "SwiftPunk", "age": 35 }
"""

struct CustomType: Decodable {
    let name: String
    let age: Int
}

func decoderFunction<T: Decodable>(json: String, decodedValue: (Result<T,Error>) -> Void) {
    decodedValue(Result {
        try JSONDecoder().decode(T.self, from: Data(json.utf8))
    })
}

And call it

decoderFunction(json: stringOfJSON) { (result : Result<CustomType,Error>) in
    
    switch result {
        case .success(let value): print(value)
        case .failure(let error): print(error)
    }
}
  • Related