【问题标题】:JSONDecoder with multiple date formats?具有多种日期格式的 JSONDecoder?
【发布时间】:2020-08-24 07:52:40
【问题描述】:

我有 2 种来自 api 的日期。我需要一起解码。但我没有找到任何解决方案。我需要在这段代码中添加"yyyy-MM-dd'T'HH:mm:ssZ" 格式。我该怎么做?

    func run<T: Decodable>(_ request: URLRequest, _ decoder: JSONDecoder = JSONDecoder()) -> AnyPublisher<Response<T>, Error> {
    return URLSession.shared
        .dataTaskPublisher(for: request)
        .receive(on: DispatchQueue.main)
        .tryMap { result -> Response<T> in
            self.dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
            decoder.dateDecodingStrategy = .formatted(self.dateFormatter)
            let value = try decoder.decode(T.self, from: result.data)
            return Response(value: value, response: result.response)
        }
        .eraseToAnyPublisher()
}

【问题讨论】:

  • 您能否澄清一下何时需要使用 format1 以及何时需要使用 format2?在同一个 JSON 中?在不同的?您是否确切知道它们在哪里使用,或者如果成功,您是否必须尝试?根据这一点,答案会有所不同。
  • func run 为我的所有项目工作。但只有一种不同的 json 结果(不同的结构)返回不同的时间格式。我不想为一个结果添加更多功能。
  • 视情况而定。你有参数JSONDecoder = JSONDecoder(),我会把参数和它的dateFormatter放在这里,不会在trypMap()中覆盖它,或者只是在你的方法中添加一个DateFormatter参数。
  • 我可以把它放在哪里?当我不把它放在这里时,这个日期的json返回空白。
  • 各种可能的想法:pastebin.com/sZse166b

标签: swift request combine dateformatter


【解决方案1】:

另一种方法是自定义dateDecodingStrategyISO8601DateFormatter,它能够根据给定的字符串指定日期格式

func run<T: Decodable>(_ request: URLRequest, _ decoder: JSONDecoder = JSONDecoder()) -> AnyPublisher<Response<T>, Error> {
return URLSession.shared
    .dataTaskPublisher(for: request)
    .receive(on: DispatchQueue.main)
    .tryMap { result -> Response<T> in
        decoder.dateDecodingStrategy = .custom { decoder -> Date in
            let container = try decoder.singleValueContainer()
            let dateFormatter = ISO8601DateFormatter()
            let dateString = try container.decode(String.self)
            if !dateString.hasSuffix("Z") {                            
                dateFormatter.formatOptions.remove(.withTimeZone) 
            }
            if let isoDate = dateFormatter.date(from: dateString) {
                return isoDate 
            } else {
                throw DecodingError.dataCorruptedError(in: container, debugDescription: "Wrong Date Format")
            }
        }
        let value = try decoder.decode(T.self, from: result.data)
        return Response(value: value, response: result.response)
    }
    .eraseToAnyPublisher()
}

【讨论】:

  • 谢谢它的工作,但这条线返回错误return dateFormatter.date(from: dateString) ?? throw DecodingError.dataCorruptedError(in: container, debugDescription: "Wrong Date Format")我这样使用return dateFormatter.date(from: dateString)!
  • 我不会那样做,如果日期格式与两种格式不匹配会导致崩溃。请查看编辑。
【解决方案2】:

您可以通过实现init(from decoder: Decoder)来实现自定义解码行为

https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types

【讨论】:

    猜你喜欢
    • 2017-11-24
    • 2019-09-14
    • 1970-01-01
    • 1970-01-01
    • 2021-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多