Swift 4 JSON Decodable with multidimensional and multitype array

后端 未结 5 1441
天命终不由人
天命终不由人 2020-11-30 13:32
{
\"values\":[
[1,1,7,\"Azuan Child\",\"Anak Azuan\",\"12345\",\"ACTIVE\",\"Morning\",7,12,\"2017-11-09 19:45:00\"],
[28,1,0,\"Azuan Child2\",\"Amran\",\"123456\",\"         


        
5条回答
  •  有刺的猬
    2020-11-30 13:51

    This answer is build on top of the answer by @Orkhan Alikhanov

    Since the values are Int or String, we can better represent them with an enum in place of Any.

    The following code can be pasted into Playground

    JSON

    So let's start with the JSON

    let data = """
    {
        "values": [
            [1, 1, 7, "Azuan Child", "Anak Azuan", "12345", "ACTIVE", "Morning", 7, 12, "2017-11-09 19:45:00"],
            [28, 1, 0, "Azuan Child2", "Amran", "123456", "ACTIVE", "Evening", 1, 29, "2017-11-09 19:45:00"]
        ]
    }
    """.data(using: .utf8)!
    

    Data Model

    Now we can define our model (which will be Decodable)

    enum IntOrString: Decodable {
    
        case int(Int)
        case string(String)
    
        init(from decoder: Decoder) throws {
    
            if let string = try? decoder.singleValueContainer().decode(String.self) {
                self = .string(string)
                return
            }
    
            if let int = try? decoder.singleValueContainer().decode(Int.self) {
                self = .int(int)
                return
            }
    
            throw IntOrStringError.intOrStringNotFound
        }
    
        enum IntOrStringError: Error {
            case intOrStringNotFound
        }
    }
    

    As you can see we are explicitly saying that each value will be an Int or a String.

    Response

    And of course we need our Response type.

    struct Response: Decodable {
        var values: [[IntOrString]]
    }
    

    Decoding

    Now we can safely decode the JSON

    if let response = try? JSONDecoder().decode(Response.self, from: data) {
        let values = response.values
    
        for value in values {
            for intOrString in value {
                switch intOrString {
                case .int(let int): print("It's an int: \(int)")
                case .string(let string): print("It's a string: \(string)")
                }
            }
        }
    }
    

    Output

    It's an int: 1
    It's an int: 1
    It's an int: 7
    It's a string: Azuan Child
    It's a string: Anak Azuan
    It's a string: 12345
    It's a string: ACTIVE
    It's a string: Morning
    It's an int: 7
    It's an int: 12
    It's a string: 2017-11-09 19:45:00
    It's an int: 28
    It's an int: 1
    It's an int: 0
    It's a string: Azuan Child2
    It's a string: Amran
    It's a string: 123456
    It's a string: ACTIVE
    It's a string: Evening
    It's an int: 1
    It's an int: 29
    It's a string: 2017-11-09 19:45:00
    

提交回复
热议问题