如何解码 Swift 中的字典 JSON 响应?

How to decode dictionary JSON response in Swift?

struct Chat: Codable, Identifiable {
    let id =  UUID()
    var Messages: [Messages]
}


class ChatApi : ObservableObject{
    @Published var chats = Chat()
    
    func loadData(completion:@escaping (Chat) -> ()) {
        let urlString = prefixUrl+"/room"
        let url = NSURL(string: urlString as String)!
        var request = URLRequest(url: url as URL)

        request.setValue(accessKey, forHTTPHeaderField: "X-Access-Key-Id")
        request.setValue(secretkey, forHTTPHeaderField: "X-Access-Key-Secret")
        
        URLSession.shared.dataTask(with: request) { data, response, error in
            let chats = try! JSONDecoder().decode(Chat.self, from: data!)
            print(chats)
            DispatchQueue.main.async {
                completion(chats)
            }
        }.resume()
        
    }
}

我无法使用 Swift 解码以下 JSON 响应。

{
    "Messages": [
        {...}
    ]
}

以上方法我都试过了,Xcode一直报错。虽然我可以用另一个像这样的函数来解码 JSON 响应

[
    {...},
    {...},
    {...}
]

我能够解码 JSON 作为数组而非字典返回的响应。

解码响应示例

{
    "Messages": [
        {
            "_id": "MS4mMbTXok8g",
            "_created_at": "2022-04-05T10:58:54Z",
            "_created_by": {
                "_id": "Us123",
                "Name": "John Doe",
            },
            "_modified_at": "2022-04-05T10:58:54Z",
            "Type": "Message",
            "_raw_content": "ss",
            "RoomId": "Ro1234",
        },
        {
            "_id": "MS4m3oYXadUV",
            "_created_at": "2022-04-04T15:22:21Z",
            "_created_by": {
                "_id": "Us678",
                "Name": "Jim Lane",
            },
            "_modified_at": "2022-04-04T15:22:21Z",
            "Type": "Message",
            "_raw_content": "ss",
            "RoomId": "Ro1234",
        }
    ]
}

我使用的数据模型是

struct CreatedBy: Codable {
    var _id: String
    var Name: String
}    
struct Messages: Codable {
    var _id: String
    var _created_by: CreatedBy?
    var `Type`: String?
    var _raw_content: String
}

struct Chat: Codable, Identifiable {
    let id =  UUID()
    var Messages: [Messages]
}

编译前的错误信息是Editor placeholder in source file

我将向您介绍几个有助于处理 JSON 解码的站点:JSON Formatter & Validator 和 Quicktype。第一个确保您正在处理的 JSON 实际上是有效的,并将其格式化为人类可读的形式。第二个将编写实际的可解码结构。这些并不完美,您可能想要编辑它们,但它们会在您学习的同时完成工作。

你一发布你的数据模型,我就看出了问题所在。您的变量之一是:

var `Type`: String?

编译器看到 ` 并认为它应该是一个占位符。您不能在代码中使用它们。

此外,虽然没有发布任何代码,但我不确定您是否需要制作 Chat Identifiable,而不是 Messages,后者可能是,但不是。我会切换或至少添加 IdentifiableMessages。我还做了 CreatedBy Identifiable 因为它也有一个独特的 id.

您遗漏的另一件事是 CodingKeys 枚举,这将使您的代码更具可读性。此 t运行 将键从您在 JSON 中获得的内容转换为您希望变量实际成为的内容。我 运行 你 JSON 浏览了以上网站,结果是这样的:

// MARK: - Chat
struct Chat: Codable {
    let messages: [Message]

    enum CodingKeys: String, CodingKey {
        case messages = "Messages"
    }
}

// MARK: - Message
struct Message: Codable, Identifiable {
    let id: String
    let createdAt: Date
    let createdBy: CreatedBy
    let modifiedAt: Date
    let type, rawContent, roomID: String

    enum CodingKeys: String, CodingKey {
        case id = "_id"
        case createdAt = "_created_at"
        case createdBy = "_created_by"
        case modifiedAt = "_modified_at"
        case type = "Type"
        case rawContent = "_raw_content"
        case roomID = "RoomId"
    }
}

// MARK: - CreatedBy
struct CreatedBy: Codable, Identifiable {
    let id, name: String

    enum CodingKeys: String, CodingKey {
        case id = "_id"
        case name = "Name"
    }
}

这为您提供了传统的 Swift 变量,与 JSON 为您提供的蛇形情况相反。在您的代码中试试这个,如果您还有其他问题,请告诉我们。