You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift Encodable如何将nil属性编码为空JSON对象

解决方案

Swift 内置的 JSONEncoder 对可选值的默认编码策略是:如果可选值为 nil,会自动忽略对应的键,不会写入最终的JSON结构中,这就是你当前代码不会输出bar字段的原因。

要实现nil编码为空JSON对象{}的需求,可以用下面两种方案:


方案1:手动实现Encodable协议

重写Foo的encode方法,单独处理bar为nil的场景,适合只有少数字段需要特殊处理的情况:

struct Foo: Encodable {
    let id = 10
    let bar: Bar? = nil
    
    enum CodingKeys: String, CodingKey {
        case id, bar
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(id, forKey: .id)
        if let bar = bar {
            try container.encode(bar, forKey: .bar)
        } else {
            // nil时编码为空字典,对应JSON空对象结构
            try container.encode([String: Any](), forKey: .bar)
        }
    }
}

struct Bar: Encodable {
    let number: Int
}

// 测试代码
let data = try! JSONEncoder().encode(Foo())
print(String(data: data, encoding: .utf8)!)
// 输出:{"id":10,"bar":{}}

方案2:属性包装器通用处理

如果项目中有大量类似需求,可以定义属性包装器复用逻辑,不用每个结构体都手写编码方法:

// 定义通用属性包装器
@propertyWrapper
struct EncodeNilAsEmptyObject<T: Encodable>: Encodable {
    var wrappedValue: T?
    
    init(wrappedValue: T?) {
        self.wrappedValue = wrappedValue
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        if let value = wrappedValue {
            try container.encode(value)
        } else {
            try container.encode([String: String]())
        }
    }
}

// 业务层直接使用标记即可
struct Foo: Encodable {
    let id = 10
    @EncodeNilAsEmptyObject let bar: Bar? = nil
}

struct Bar: Encodable {
    let number: Int
}

注意:如果同时需要支持Decodable能力,还需要对应实现空对象解码为nil的逻辑,仅编码场景以上代码可以直接使用。

内容的提问来源于stack exchange,提问作者Silis Alin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 05:57:03