繁体   English   中英

无法从 JSON API 获取

[英]Unable to GET from JSON API

我已尝试遵循各种教程,但无法从该 API 获取数据。 我确实设法在更简单的 JSON 上取得了成功,但是这个正在占用我的时间。 首先,JSON:

{
    "object": {
        "array": [
            {
                "id": 48,
                "name": "Job No.# 48",
                "description": "blah",
                "start_at": "2021-03-05T13:15:00.000+11:00",
                "end_at": "2021-03-05T14:15:00.000+11:00",
                "map_address": "blah road"
            },
            {
                "id": 56,
                "name": "Job No.# 56",
                "description": "Do it",
                "start_at": "2021-06-22T11:30:00.000+10:00",
                "end_at": "2021-06-22T13:30:00.000+10:00",
                "map_address": " blah"
            }
        ],
        "person": {
            "id": 52,
            "first_name": "Bob",
            "last_name": "Newby",
            "mobile": "0401111111",
            "email": "bob@mail.com"
        }
    }
}

现在我尝试解码它:

struct api_data: Codable {
    let object : Object
}

struct Object: Codable {
    let array : [array]
    let person : Person
}

struct array: Codable, Identifiable {
    let id : Int?
    let start_at, end_at : Date?
    let duration : Float?
    let cancellation_type : String?
    let name, description, address, city, postcode, state : String?
}

struct Person: Codable, Identifiable {
    let id : Int?
    let first_name, last_name, mobile, email : String?
}

class FetchShifts: ObservableObject {
  @Published var shifts = [Shifts]()
     
    init() {
        let url = URL(string: "realURLhiddenForPrivacy")!
        var request = URLRequest(url: url)
        request.httpMethod = "GET"
        request.setValue("myToken", forHTTPHeaderField: "Authorization")
        URLSession.shared.dataTask(with: request) {(data, response, error) in
            do {
                if let array_data = data {
                    let array_data = try JSONDecoder().decode([array].self, from: array_data)
                    DispatchQueue.main.async {
                        self.array = array_data
                    }
                } else {
                    print("No data")
                }
            } catch {
                print(error)
            }
        }.resume()
    }
}

以及我如何尝试呈现它:

    @ObservedObject var fetch = FetchArray()
    
    var body: some View {
        VStack {
            List(array.shifts) { shft in
                VStack(alignment: .leading) {
                    Text(shft.name!)
                }
            }
        }
    }
}
}

任何帮助表示赞赏,不知道我在这里哪里出错了,在教程中花了 5-7 个小时。

如果您不熟悉它,我总是建议使用 app.quicktype.io 从 JSON 生成模型。 这是它产生的结果:

// MARK: - Welcome
struct Welcome: Codable {
    let status: String
    let payload: Payload
}

// MARK: - Payload
struct Payload: Codable {
    let shifts: [Shift]
    let worker: Worker
}

// MARK: - Shift
struct Shift: Codable, Identifiable {
    let id: Int
    let name, shiftDescription, startAt, endAt: String
    let mapAddress: String

    enum CodingKeys: String, CodingKey {
        case id, name
        case shiftDescription = "description"
        case startAt = "start_at"
        case endAt = "end_at"
        case mapAddress = "map_address"
    }
}

// MARK: - Worker
struct Worker: Codable {
    let id: Int
    let firstName, lastName, mobile, email: String

    enum CodingKeys: String, CodingKey {
        case id
        case firstName = "first_name"
        case lastName = "last_name"
        case mobile, email
    }
}

然后,要解码,您可以执行以下操作:

do {
    let decoded = try JSONDecoder().decode(Welcome.self, from: shift_data)
    let shifts = decoded.payload.shifts
} catch {
    print(error)
}

请注意,在 Swift 中,通常的做法是使用驼峰命名,而不是蛇命名,因此您会看到CodingKeys一些转换(也有自动执行此操作的方法)。


更新,基于评论:

您的代码将是:

 if let shiftData = data { do { let decoded = try JSONDecoder().decode(Welcome.self, from: shiftData) DispatchQueue.main.async { self.shifts = decoded.payload.shifts } } catch { print(error) } }

您可以为 JSON 解码器自动使用keyDecodingStrategy = .convertFromSnakeCase ,而不是定义自定义键,并且可以指定自定义日期格式,甚至在解码器实现中抛出自定义错误。

struct Worker: Codable {
    let id: Int
    let firstName: String?
    let lastName: String?
    let mobile: String?
    let email: String?
}
struct Shift: Codable, Identifiable {
    let id: Int
    let name: String?
    let description: String?
    let startAt: Date?
    let endAt: Date?
    let mapAddress: String?
}
struct Payload: Codable {
    let shifts: [Shift]?
    let worker: Worker?
}

struct Response: Codable {
    let status: String
    let payload: Payload?
}

class MyCustomDecoder: JSONDecoder {
    override init() {
        super.init()
        self.keyDecodingStrategy = .convertFromSnakeCase
        
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
        self.dateDecodingStrategy = .formatted(dateFormatter)
    }
}

// Usage
if let data = json.data(using: .utf8) {
    let response = try MyCustomDecoder().decode(Response.self, from: data)
    print(response)
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM