我正在try 从URL解码一个JSON,但我的代码无法解码该JSON.

This is the json: json

这是我的模型对象:

struct User: Decodable, Identifiable {
    let name: String
    let birthdate: Date
    let id: Int
}

这是我的Fetch用户代码:

 func fetchUsers() async throws -> [User]? {
        let endPoint = EndPoint.users.rawValue
        guard let url = URL(string: endPoint) else {
            print("Invalid URL")
            return nil
        }
        let urlRequest = URLRequest(url: url)
        do {
            let (json, _) = try await URLSession.shared.data(for: urlRequest)
            return try JSONDecoder().decode([User].self, from: json)
         } catch {
             print(error)
         }
    }
    // create user with async/await
}

when I debug I get this data result of URLSession: json data

推荐答案

问题出在您的JSONDecoder日期DecodingStrategy中.默认策略称为deferredToDate,这意味着它期待timeIntervalSinceReferenceDate.您需要一个定制的日期格式来解析您的ISO8601日期格式.判断一下这个How to convert a date string with optional fractional seconds using Codable in Swift?.

只需创建一个包含和不包含小数秒的自定义DateForMatter is8601:

extension Formatter {
    static let iso8601withFractionalSeconds: DateFormatter = {
        let formatter = DateFormatter()
        formatter.calendar = Calendar(identifier: .iso8601)
        formatter.locale = Locale(identifier: "en_US_POSIX")
        formatter.timeZone = TimeZone(secondsFromGMT: 0)
        formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"
        return formatter
    }()
    static let iso8601: DateFormatter = {
        let formatter = DateFormatter()
        formatter.calendar = Calendar(identifier: .iso8601)
        formatter.locale = Locale(identifier: "en_US_POSIX")
        formatter.timeZone = TimeZone(secondsFromGMT: 0)
        formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
        return formatter
    }()
}

和一个自定义的日期解码策略:

extension JSONDecoder.DateDecodingStrategy {
    static let customISO8601 = custom {
        let container = try $0.singleValueContainer()
        let string = try container.decode(String.self)
        if let date = Formatter.iso8601withFractionalSeconds.date(from: string) ?? Formatter.iso8601.date(from: string) {
            return date
        }
        throw DecodingError.dataCorruptedError(in: container, debugDescription: "Invalid date: \(string)")
    }
}

现在,您可以正确设置JSONDecoder日期DecodingStrategy:

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

并使用该解码器解析您的JSON字符串.请注意,如果您使用Try?您正在丢弃应该用来调试问题的错误:

    return try decoder.decode([User].self, from: json) 
} catch {
    print(error)
}

Ios相关问答推荐

ITMS—91053:Flutter Project中缺少API声明

带外部笔划的圆形进度视图

磁盘上的Objective-C ISA指针与实例化对象时的比较

Swift-如何通过Case Let访问模型变量

iOS应用程序冻结在UICollectionView代码,但我没有';没有任何UICollectionViews

SwiftUI - 搜索栏和导航标题之间的空间太大

如何删除点击时按钮的不透明动画?

在自定义 ButtonStyle 中修改形状 colored颜色

iOS 16.4 更新后 Xcode 14.3 构建错误:找不到 libarclite_iphoneos.a,链接器命令失败

从 PHAssets 生成图像时,iOS 应用程序因内存问题而崩溃

视觉扫描无法识别 iOS16 上的 GS1 条码特殊字符

如何在应用程序中显示我的小部件的快照?

为 ColorPicker 创建一个名为 Color 的计算变量的绑定

Xcode 不支持 iOS 15.6

将值传递给导航链接视图中的文本框

try 在 iOS 中分发 Flutter 应用程序时出现Invalid Provisioning Profile Signature错误

UICollectionView - 动态单元格高度?

关闭通过模态 segue 显示的视图

将视图控制器从一个情节提要移动或复制到另一个情节提要

为给定的 UIColor 获取更亮和更暗的 colored颜色 变化