简体   繁体   English

使用 JSONDecoder 和 Swift 将 nil 转换为空字符串

[英]Convert nil to empty string using JSONDecoder and Swift

I am using Swift 4 and JSONDecoder .我正在使用 Swift 4 和JSONDecoder I have the following structure:我有以下结构:

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

Note: the fields cannot be made optional.注意:这些字段不能是可选的。

Now I have a JSON string:现在我有一个 JSON 字符串:

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

And to decode it, I use the following:为了解码它,我使用以下内容:

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

Everything works fine except the null data gets converted to nil.一切正常,除了空数据被转换为 nil。 My question is, what would be the easiest way to convert incoming nil to an empty string ("")?我的问题是,将传入的 nil 转换为空字符串 ("") 的最简单方法是什么?

I would like to do this with the minimum amount of code but I'm not sure about the correct approach and at what point can the nil be converted to an empty string.我想用最少的代码来做到这一点,但我不确定正确的方法以及什么时候可以将 nil 转换为空字符串。 Thank you beforehand.先谢谢了。

You can use backing ivars:您可以使用支持 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"
    }
}

Due to the custom CodingKeys , the JSON decoder will actually decode to _cnum and _cname , which are optional strings.由于自定义CodingKeys ,JSON 解码器实际上会解码为_cnum_cname ,它们是可选字符串。 We convert nil to empty string in the property getters.我们在属性 getter 中将 nil 转换为空字符串。

You can use decodeIfPresent method.您可以使用 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"

    }
}

You should make a computed variable that will have the original value if it's not nil and an empty string if it is.您应该创建一个计算变量,如果它不是 nil,它将具有原始值,如果它是空字符串。

var cnameNotNil: String {
    return cname ?? ""
}

The usual way is to write an initializer which handles the custom behavior.通常的方法是编写一个处理自定义行为的初始化程序。 The null value is caught in an extra do - catch block. 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 = "" }
    }
}

Use decodeIfPresent if the value from response might be null如果响应中的值可能为空,则使用decodeIfPresent

cnum = try container.decode(String.self, forKey: .cnum)
cname = try container.decodeIfPresent(String.self, forKey: .cname)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM