如何解码 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
,后者可能是,但不是。我会切换或至少添加 Identifiable
到 Messages
。我还做了 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 为您提供的蛇形情况相反。在您的代码中试试这个,如果您还有其他问题,请告诉我们。
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
,后者可能是,但不是。我会切换或至少添加 Identifiable
到 Messages
。我还做了 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 为您提供的蛇形情况相反。在您的代码中试试这个,如果您还有其他问题,请告诉我们。