0

我正在使用 Swift 4 和JSONDecoder. 我有以下结构:

struct Customer: Codable {
    var id: Int!
    var cnum: String!
    var cname: String!
}

注意:这些字段不能设为可选。

现在我有一个 JSON 字符串:

[
    {
        "id": 1,
        "cnum": "200",
        "cname": "Bob Smith"
    },
    {
        "id": 2,
        "cnum": "201",
        "cname": null
    }
]

为了解码它,我使用以下内容:

let decoder = JSONDecoder()
let customers = try decoder.decode([Customer].self, from: json)

一切正常,除了 null 数据被转换为 nil。我的问题是,将传入的 nil 转换为空字符串(“”)的最简单方法是什么?

我想用最少的代码来做到这一点,但我不确定正确的方法以及在什么时候可以将 nil 转换为空字符串。事先谢谢你。

4

5 回答 5

4

您可以使用支持 ivars:

struct Customer: Codable {
    var id: Int
    var cnum: String {
        get { _cnum ?? "" }
        set { _cnum = newValue }
    }
    var cname: String {
        get { _cname ?? "" }
        set { _cname = newValue }
    }
    
    private var _cnum: String?
    private var _cname: String?
    private enum CodingKeys: String, CodingKey {
        case id, _cnum = "cnum", _cname = "cname"
    }
}

由于 custom CodingKeys,JSON 解码器实际上将解码为_cnum_cname,它们是可选字符串。我们在属性 getter 中将 nil 转换为空字符串。

于 2018-02-02T01:27:59.367 回答
2

您可以使用 decodeIfPresent 方法。

struct Source : Codable {

    let id : String?


    enum CodingKeys: String, CodingKey {
        case id = "id"

    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        id = try values.decodeIfPresent(String.self, forKey: .id) ?? "Default value pass"

    }
}
于 2019-05-15T09:49:24.710 回答
1

您应该创建一个计算变量,如果它不是 nil,它将具有原始值,如果它是空字符串。

var cnameNotNil: String {
    return cname ?? ""
}
于 2018-02-01T13:45:34.493 回答
0

如果响应中的值可能为空,请使用decodeIfPresent

cnum = try container.decode(String.self, forKey: .cnum)
cname = try container.decodeIfPresent(String.self, forKey: .cname)
于 2018-07-13T01:54:00.377 回答
0

通常的方法是编写一个处理自定义行为的初始化程序。该null值被捕获在一个额外的do - catch块中。

struct Customer: Codable {
    var id: Int
    var cnum: String
    var cname: String

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        id = try container.decode(Int.self, forKey: .id)
        cnum = try container.decode(String.self, forKey: .cnum)
        do { cname = try container.decode(String.self, forKey: .cname) }
        catch { cname = "" }
    }
}
于 2018-02-01T14:05:30.437 回答