Swift中如何通过JSONEncoder/Codable将Date转为无小数Unix秒数
解决Codable序列化Date为无小数Unix秒数的问题
嘿,这个场景我太熟悉了!默认的.secondsSince1970确实会输出带毫秒的浮点数,而DateFormatter又没法直接输出数值型的Unix秒数,完全重写Codable又太麻烦。给你几个简单高效的方案:
方案一:直接自定义dateEncodingStrategy闭包
这是最直接的方法,不用改动你的模型代码,只需要给JSONEncoder设置自定义的日期编码策略就行:
let encoder = JSONEncoder() encoder.dateEncodingStrategy = .custom { date, encoder in // 把Date的时间戳转成整数秒(自动舍去小数部分) let unixSeconds = Int(date.timeIntervalSince1970) var container = encoder.singleValueContainer() try container.encode(unixSeconds) } // 测试示例 struct Event: Codable { let name: String let timestamp: Date } let event = Event(name: "Test", timestamp: Date()) if let data = try? encoder.encode(event), let jsonString = String(data: data, encoding: .utf8) { print(jsonString) // 输出会是 {"name":"Test","timestamp":1699999999} 这类纯整数格式 }
这个闭包逻辑很直白:把Date的timeIntervalSince1970转成Int类型(自动丢弃小数部分),再编码成数值类型,这样序列化后的JSON里就是无小数的Unix秒数了。
方案二:封装复用的编码器
如果项目里很多地方都需要这个逻辑,建议封装成扩展,方便随时调用:
extension JSONEncoder { static var unixSecondsEncoder: JSONEncoder { let encoder = JSONEncoder() encoder.dateEncodingStrategy = .custom { date, encoder in try encoder.encode(Int(date.timeIntervalSince1970)) } return encoder } } // 使用时直接调用 let data = try JSONEncoder.unixSecondsEncoder.encode(event)
配套的解码策略(可选)
如果需要反序列化对应的JSON,记得给JSONDecoder设置对应的解码逻辑:
let decoder = JSONDecoder() decoder.dateDecodingStrategy = .custom { decoder in let timestamp = try decoder.singleValueContainer().decode(Int.self) return Date(timeIntervalSince1970: TimeInterval(timestamp)) }
为什么不用DateFormatter?
你说得没错,DateFormatter的dateFormat确实没有直接输出Unix秒数的格式——它主要负责字符串格式的日期转换,而Unix秒数是数值类型,所以用自定义闭包是最适配的方案,比绕弯子用DateFormatter高效多了。
内容的提问来源于stack exchange,提问作者mm282
相关产品推荐
相关产品推荐

