Swift 4 JSON Decodable simplest way to decode type change

后端 未结 8 2062
天涯浪人
天涯浪人 2020-12-01 05:47

With Swift 4\'s Codable protocol there\'s a great level of under the hood date and data conversion strategies.

Given the JSON:

{
    \"name\": \"Bob\         


        
8条回答
  •  北荒
    北荒 (楼主)
    2020-12-01 05:59

    I know that this is a really late answer, but I started working on Codable couple of days back only. And I bumped into a similar issue.

    In order to convert the string to floating number, you can write an extension to KeyedDecodingContainer and call the method in the extension from init(from decoder: Decoder){}

    For the problem mentioned in this issue, see the extension I wrote below;

    extension KeyedDecodingContainer {
    
        func decodeIfPresent(_ type: Float.Type, forKey key: K, transformFrom: String.Type) throws -> Float? {
    
            guard let value = try decodeIfPresent(transformFrom, forKey: key) else {
                return nil
            }
            return Float(value)
        }
    
        func decode(_ type: Float.Type, forKey key: K, transformFrom: String.Type) throws -> Float {
    
            guard let valueAsString = try? decode(transformFrom, forKey: key),
                let value = Float(valueAsString) else {
    
                throw DecodingError.typeMismatch(
                    type, 
                    DecodingError.Context(
                        codingPath: codingPath, 
                        debugDescription: "Decoding of \(type) from \(transformFrom) failed"
                    )
                )
            }
            return value
        }
    }
    

    You can call this method from init(from decoder: Decoder) method. See an example below;

    init(from decoder: Decoder) throws {
    
        let container = try decoder.container(keyedBy: CodingKeys.self)
    
        taxRate = try container.decodeIfPresent(Float.self, forKey: .taxRate, transformFrom: String.self)
    }
    

    In fact, you can use this approach to convert any type of data to any other type. You can convert string to Date, string to bool, string to float, float to int etc.

    Actually to convert a string to Date object, I will prefer this approach over JSONEncoder().dateEncodingStrategy because if you write it properly, you can include different date formats in the same response.

    Hope I helped.

    Updated the decode method to return non-optional on suggestion from @Neil.

提交回复
热议问题