当struct属性为可选时,如何检测数据值是否为nil

时间:2019-04-03 06:10:37

标签: json swift generics codable

使用Codable解析数据不会失败。

当我使用泛型时,如果字段不同,那么我希望解析失败,然后我的对象字段

struct someStruct: Codable {
    var name: String?
    var age: Int?
}

JSON :
{
    "some_key": 123
}

3 个答案:

答案 0 :(得分:0)

您应该使用 Codable 解析数据是否为零。然后,您可以像下面那样检查Struct的零值-

if let name = yourStruct.name as? String {

} else {
  //nil
}

答案 1 :(得分:0)

您可以仅将Codable与您的结构一起使用,并在解析JSON数据时使用,并且由于您在 struct 中的属性为可选,因此可以安全使用使用if-let解开值。我提供了相同的示例示例

import Foundation

let jsonData = """
    {
        "some_key": 123
    }
"""

let data = Data(jsonData.utf8)

struct someStruct: Codable {
    var name: String?
    var age: Int?
}

let decoder = JSONDecoder()

do {
    let decodedData = try decoder.decode(someStruct.self, from: data)

    // Either use this
    print(decodedData.name ?? "Name not specified")

    // Or use this
    if let name = decodedData.name {
        // Name is not nil
        // Sample Example
        print(name)
    }
    else {
        // Name is nil , Handle the situation accordingly
        // Sample Example
        print("Name not specified")
    }

} catch  {
    print("Could not parse JSON Data")
}

答案 2 :(得分:0)

因此,如果缺少某个字段,您想throw,但是如果指定了字段,但nil,则继续。 您需要实现自定义编码才能解决该问题:

enum EncodingError: Error {
    case missing
}

struct Struct: Codable {
    let age: Int
    let name: String?

    enum CodingKeys: CodingKey {
        case age
        case name
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        // normal decoding
        age = try container.decode(Int.self, forKey: .age)
        // check if key exists or throw
        guard container.contains(.name) else {
            throw EncodingError.missing
        }
        name = try container.decode(String?.self, forKey: .name)
     }
}

let correctData = """
{
    "age": 34,
    "name": null
}
""".data(using: .utf8)!

let failData = """
{
    "age": 33
}
""".data(using: .utf8)!

do {
    let decoder = JSONDecoder()
    let encoded = try decoder.decode(Struct.self, from: correctData) // succeeds
    let fail = try decoder.decode(Struct.self, from: failData) // fails
} catch(let error) where error is EncodingError {
    error
} catch {
    error
}