首页 > 解决方案 > 使用 Codable 将空字符串解码为 nil

问题描述

正常情况:

{
    "maintenance": true
}

{
    "maintenance": false
}

如果没有维修站,就会变成empty string

{
    "maintenance": ""
}

nil如果维护是json中的空字符串,我想拥有

struct Demo: Codable {
    var maintenance: Bool?
}

有什么好的方法吗?

标签: iosjsonswiftstring

解决方案


您需要尝试解码 Bool,捕获错误,尝试解码字符串并检查它是否为空字符串,否则抛出错误。这将确保您不会丢弃任何解码错误,即使它是一个字符串但不是空的:


struct Demo: Codable {
    var maintenance: Bool?
}

struct Root: Codable {
    var maintenance: Bool?
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        do {
            maintenance = try container.decode(Bool.self, forKey: .maintenance)
        } catch {
            guard try container.decode(String.self, forKey: .maintenance) == "" else {
                throw error
            }
            maintenance = nil
        }
    }
}

游乐场测试:

let json1 = """
{
    "maintenance": true
}
"""
let json2 = """
{
    "maintenance": false
}
"""
let json3 = """
{
    "maintenance": ""
}
"""
let json4 = """
{
    "maintenance": "false"
}
"""

do {
    let root1 = try JSONDecoder().decode(Root.self, from: Data(json1.utf8))
    print("root1", root1)
} catch {
    print(error)
}

do {
    let root2 = try JSONDecoder().decode(Root.self, from: Data(json2.utf8))
    print("root2", root2)
} catch {
    print(error)
}

do {
    let root3 = try JSONDecoder().decode(Root.self, from: Data(json3.utf8))
    print("root3", root3)
} catch {
    print(error)
}

do {
    let root4 = try JSONDecoder().decode(Root.self, from: Data(json4.utf8))
    print("root4", root4)
} catch {
    print(error)
}

这将打印

root1 根(维护:可选(true))
root2 根(维护:可选(假))
root3 根(维护:nil)
typeMismatch(Swift.Bool,Swift.DecodingError.Context(codingPath:[CodingKeys(stringValue:“维护”, intValue: nil)], debugDescription: "预期解码 Bool 但找到了一个字符串/数据。",底层错误: nil))


推荐阅读