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

Swift中Encodable类如何为不同日期属性设置不同编码格式?

为Encodable类的不同Date属性设置不同编码格式

问题描述

我有一个遵循Encodable协议的类,包含两个Date类型的属性。编码为JSON字符串时,希望两个日期使用不同格式:

  • date1采用ISO8601格式(如"2022-10-24T22:03:43Z")
  • date2采用时间戳格式(如688342014.16646099)

尝试示例代码后未能实现,请问该如何为不同属性设置不同日期格式?是否需要重写JSONEncoder.encode()方法?

示例代码:

func getString() -> String? {
    let encoder = JSONEncoder()
    encoder.outputFormatting = .prettyPrinted
    encoder.dateEncodingStrategy = .iso8601
    
    guard let data = try? encoder.encode(TwoDates()) else { return nil }
    guard let dataString = String(data: data, encoding: .utf8) else { return nil }
    return dataString
}

class TwoDates: Encodable {
    public var date1 = Date()
    public var date2 = Date()
    
    public func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try? container.encode(date1, forKey: .date1)
        try? container.encode(date1, forKey: .date2) // 此处错误重复编码date1
    }
    
    enum CodingKeys: String, CodingKey {
        case date1 = "date1"
        case date2 = "date2"
    }
}

解决方案

不需要重写JSONEncoder.encode()方法,只需在自定义的encode(to:)方法中分别处理两个Date属性的编码逻辑即可:

  1. 对于date1,直接利用encoder已设置的.iso8601编码策略完成编码。
  2. 对于date2,将其转换为时间戳(通过Date的timeIntervalSince1970属性获取带小数的秒数),再编码这个数值类型即可输出时间戳格式。
  3. 替换原代码中错误的重复编码逻辑,同时改用try替代try?,避免忽略编码错误,方便调试。

修改后的完整代码:

func getString() -> String? {
    let encoder = JSONEncoder()
    encoder.outputFormatting = .prettyPrinted
    encoder.dateEncodingStrategy = .iso8601
    
    do {
        let data = try encoder.encode(TwoDates())
        return String(data: data, encoding: .utf8)
    } catch {
        print("编码失败:\(error)")
        return nil
    }
}

class TwoDates: Encodable {
    public var date1 = Date()
    public var date2 = Date()
    
    public func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        // 按ISO8601格式编码date1
        try container.encode(date1, forKey: .date1)
        // 将date2转为时间戳后编码
        try container.encode(date2.timeIntervalSince1970, forKey: .date2)
    }
    
    enum CodingKeys: String, CodingKey {
        case date1 = "date1"
        case date2 = "date2"
    }
}

代码说明

  • date1的编码依赖JSONEncoder设置的dateEncodingStrategy = .iso8601,会自动生成符合ISO8601标准的字符串。
  • date2通过timeIntervalSince1970获取从1970年1月1日00:00:00 UTC到当前日期的秒数(带小数精度),编码该Double值后,JSON中会直接显示为时间戳格式。
  • 使用do-catch捕获错误,能及时定位编码过程中出现的问题,提升调试效率。

内容的提问来源于stack exchange,提问作者Bartosz Jarosz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 07:25:18