Search code examples
jsonparsingbooleanswift4jsondecoder

What parsing object when property can be integer or bool?


Sometimes server sends me property as bool (true, false). Sometimes server sends me property as an integer (0,1).

How can I decodable this case via standard Decodable in Swift 4?

Example. I have:

final class MyOffer : Codable {
    var id = 0
    var pickupAsap: Int?

    enum CodingKeys: String, CodingKey {
         case id
         case pickupAsap = "pickup_asap"
    }
}

Responses from server are:

1) "pickup_all_day": true,

2) "pickup_all_day": 0


Solution

  • you may implement your own decode init method, get each class property from decode container, during this section, make your logic dealing with wether "asap" is an Int or Bool, sign all required class properties at last.

    here is a simple demo i made:

    class Demo: Decodable {
        var id = 0
        var pickupAsap: Int?
    
        enum CodingKeys: String, CodingKey {
            case id
            case pickupAsap = "pickup_asap"
        }
    
        required init(from decoder: Decoder) throws {
            let container = try decoder.container(keyedBy: CodingKeys.self)
            let id = try container.decode(Int.self, forKey: .id)
            let pickupAsapBool = try? container.decode(Bool.self, forKey: .pickupAsap)
            let pickupAsapInt = try? container.decode(Int.self, forKey: .pickupAsap)
            self.pickupAsap = pickupAsapInt ?? (pickupAsapBool! ? 1 : 0)
            self.id = id
        }
    }
    

    mock data:

     let jsonInt = """
    {"id": 10,
     "pickup_asap": 0
    }
    """.data(using: .utf8)!
    
    let jsonBool = """
    {"id": 10,
     "pickup_asap": true
    }
    """.data(using: .utf8)!
    

    test:

    let jsonDecoder = JSONDecoder()
    let result = try! jsonDecoder.decode(Demo.self, from: jsonInt)
    print("asap with Int: \(result.pickupAsap)")
    
    let result2 = try! jsonDecoder.decode(Demo.self, from: jsonBool)
    print("asap with Bool: \(result2.pickupAsap)")
    

    output:

    asap with Int: Optional(0)
    asap with Bool: Optional(1)
    

    for more info: Apple's encoding and decoding doc