How to parse JSON with Decodable protocol when property types might change from Int to String?

前端 未结 4 536
清歌不尽
清歌不尽 2020-12-03 16:13

I have to decode a JSON with a big structure and a lot of nested arrays. I have reproduced the structure in my UserModel file, and it works, except with one property (postco

4条回答
  •  野趣味
    野趣味 (楼主)
    2020-12-03 16:42

    You can use generic like this:

    enum Either {
        case left(L)
        case right(R)
    }
    
    extension Either: Decodable where L: Decodable, R: Decodable {
        init(from decoder: Decoder) throws {
            let container = try decoder.singleValueContainer()
            if let left = try? container.decode(L.self) {
                self = .left(left)
            } else if let right = try? container.decode(R.self) {
                self = .right(right)
            } else {
                throw DecodingError.typeMismatch(Either.self, .init(codingPath: decoder.codingPath, debugDescription: "Expected either `\(L.self)` or `\(R.self)`"))
            }
        }
    }
    
    extension Either: Encodable where L: Encodable, R: Encodable {
        func encode(to encoder: Encoder) throws {
            var container = encoder.singleValueContainer()
            switch self {
            case let .left(left):
                try container.encode(left)
            case let .right(right):
                try container.encode(right)
            }
        }
    }
    

    And then declare postcode: Either and if your model is Decodable and all other fields are Decodable too no extra code would be needed.

提交回复
热议问题