如何将日期 JSON 解码为 Swift 模型?

3 json date decoding ios swift

我需要什么样的数据模型来解码这种 json 日期格式?

\n

示例 json:

\n
{\n    createdAt: "2021-01-30T22:48:00.469Z",\n    updatedAt: "2021-01-30T22:48:00.490Z"\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我尝试使用此模型,但不断收到解码错误\xe2\x80\xa6

\n
struct Date: Decodable {\n    var createdAt: Date\n    var updatedAt: Date   \n}\n
Run Code Online (Sandbox Code Playgroud)\n

New*_*Dev 9

首先,不要命名您的自定义类型Date- 它与Date标准库冲突。我将其重命名为DateInfo

struct DateInfo: Decodable {
   var createdAt: Date
   var updatedAt: Date   
}
Run Code Online (Sandbox Code Playgroud)

然后,要将日期解码为Date,您需要设置dateDecodingStrategyJSONDecoder选择日期格式。在您的示例中,这是标准的 iso8601 格式,但带有小数秒,并且(感谢@LeoDabus)内置解码策略.iso8601不支持:

因此,如果没有小数秒,就会像这样完成:

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601

let dateInfo = try decoder.decode(DateInfo.self, from: jsonData)
Run Code Online (Sandbox Code Playgroud)

但对于小数秒,需要一些手动工作来使用ISO8601DateFormatter. 为了方便起见,我们可以使用自定义格式化程序和日期解码策略创建扩展:

extension Formatter {
   static var customISO8601DateFormatter: ISO8601DateFormatter = {
      let formatter = ISO8601DateFormatter()
      formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
      return formatter
   }()
}

extension JSONDecoder.DateDecodingStrategy {
   static var iso8601WithFractionalSeconds = custom { decoder in
      let dateStr = try decoder.singleValueContainer().decode(String.self)
      let customIsoFormatter = Formatter.customISO8601DateFormatter
      if let date = customIsoFormatter.date(from: dateStr) {
         return date
      }
      throw DecodingError.dataCorrupted(
               DecodingError.Context(codingPath: decoder.codingPath, 
                                     debugDescription: "Invalid date"))
   }
}
Run Code Online (Sandbox Code Playgroud)

其用法与内置策略类似,只是使用自定义策略:

decoder.dateDecodingStrategy = .iso8601WithFractionalSeconds
Run Code Online (Sandbox Code Playgroud)