[英]Parsing JSON With Codable in Swift
我正在嘗試在Swift中使用可編碼的方式解析JSON。 我之前已經成功完成了此操作,但是我有一個帶有一些數組的更復雜的JSON對象,遇到了麻煩。
這是我的JSON:
{
"data": [ {
"type":"player",
"id":"account.7e5b92e6612440349afcc06b7c390114",
"attributes": {
"createdAt":"2018-04-06T04:59:40Z",
"name":"bob",
"patchVersion":"",
"shardId":"pc-na",
"stats":null,
"titleId":"bluehole-pubg",
"updatedAt":"2018-04-06T04:59:40Z"
},
"relationships": {
"assets": {
"data":[]
},
"matches": {
"data": [
{"type":"match","id":"3e2a197a-1453-4569-b35b-99e337dfabc5"},
{"type":"match","id":"15f41d2f-9da2-4b95-95ca-b85e297e14b7"},
{"type":"match","id":"a42c496c-ad92-4d3e-af1f-8eaa2e200c2b"}
{"type":"match","id":"b6e33df5-4754-49da-9a0f-144842bfc306"},
{"type":"match","id":"5b357cd1-35fe-4859-a2d7-48f263120bbd"},
{"type":"match","id":"99fc5f81-c24c-4c82-ae03-cd21c94469c0"},
{"type":"match","id":"1851c88e-6fed-48e8-be84-769f20f5ee6f"},
{"type":"match","id":"e16db7ea-520f-4db0-b45d-649264ac019c"},
{"type":"match","id":"6e61a7e7-dcf5-4df5-aa88-89eca8d12507"},
{"type":"match","id":"dcbf8863-9f7c-4fc9-b87d-93fe86babbc6"},
{"type":"match","id":"0ba20fbb-1eaf-4186-bad5-5e8382558564"},
{"type":"match","id":"8b104f3b-66d5-4d0a-9992-fe053ab4a6ca"},
{"type":"match","id":"79822ea7-f204-47f8-ae6a-7efaac7e9c90"},
{"type":"match","id":"1389913c-a742-434a-80c5-1373e115e3b6"}
]
}
},
"links": {
"schema":"",
"self":"https://api.playbattlegrounds.com/shards/pc-na/players/account.7e5b92e6612440349afcc06b7c390114"
}
}],
"links": {
"self":"https://api.playbattlegrounds.com/shards/pc-na/players?filter[playerNames]=dchilds64"
},
"meta":{}
}
這是我正在使用的模型:
public struct PlayerResponse: Codable {
let data: [Player]
}
對於玩家:
public struct Player: Codable {
let type: String
let id: String
let attributes: Attributes
let relationships: Relationships
}
對於屬性:
public struct Attributes: Codable {
let name: String
let patchVersion: String
let shardId: String
let titleId: String
let updatedAt: String
}
對於關系:
public struct Relationships: Codable {
let matches: Matches
}
對於比賽:
public struct Matches: Codable {
let data: [Match]
}
匹配:
public struct Match: Codable {
let type: String
let id: String
}
解碼為:
let players = try decoder.decode([Player].self, from: jsonData)
我有運行我的網絡請求的此功能:
func getPlayerData(for name: String, completion: ((Result<[Player]>) -> Void)?) {
var urlComponents = URLComponents()
urlComponents.scheme = "https"
urlComponents.host = "api.playbattlegrounds.com"
urlComponents.path = "/shards/\(regionShard.rawValue)/players"
let playerNameItem = URLQueryItem(name: "filter[playerNames]", value: "\(name)")
urlComponents.queryItems = [playerNameItem]
guard let url = urlComponents.url else { fatalError("Could not create URL from components") }
print(url)
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.setValue("bearer \(apiKey)", forHTTPHeaderField: "Authorization")
request.setValue("application/vnd.api+json", forHTTPHeaderField: "Accept")
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
let task = session.dataTask(with: request) { (responseData, response, responseError) in
DispatchQueue.main.async {
if let error = responseError {
completion?(.failure(error))
} else if let jsonData = responseData {
let decoder = JSONDecoder()
do {
let players = try decoder.decode([Player].self, from: jsonData)
completion?(.success(players))
} catch {
completion?(.failure(error))
}
} else {
let error = NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey : "Data was not retrieved from request"]) as Error
completion?(.failure(error))
}
}
}
task.resume()
}
我面臨的問題是,當我嘗試運行網絡請求時出現此錯誤:
我認為我的可編碼結構有問題,但是我不確定。 有人可以指出正確的方向來尋找我的錯誤嗎?
如我所見,您整個玩家的反應都來自關鍵data
。 而且,您直接使用Player
編碼結構解析播放器信息,而不是使用PlayerResponse
編碼結構中的data
鍵來解析播放器信息。
要解決此問題,請將您的代碼更新為:
let players = try decoder.decode(PlayerResponse.self, from: jsonData)
希望這能解決您的問題。
我建議您從頭開始進行構建,因為JSONDecoder
的錯誤(與任何編譯器一樣)隨着結構的參與而變得越來越糟。 讓我們看看我們能走多遠:
您的Match
結構非常好聽:
public struct Match: Codable {
let type: String
let id: String
}
let decoder = JSONDecoder()
let mData = """
{"type":"match","id":"3e2a197a-1453-4569-b35b-99e337dfabc5"}
""".data(using:.utf8)!
let match = try! decoder.decode(Match.self, from:mData)
print(match)
這里沒有意外的問題。 縮短Matches
您已經遇到了第一個錯誤,而不是意外的錯誤
public struct Matches: Codable {
let data: [Match]
}
let mtchsData = """
{
"data": [
{"type":"match","id":"3e2a197a-1453-4569-b35b-99e337dfabc5"},
{"type":"match","id":"15f41d2f-9da2-4b95-95ca-b85e297e14b7"},
{"type":"match","id":"a42c496c-ad92-4d3e-af1f-8eaa2e200c2b"}
{"type":"match","id":"b6e33df5-4754-49da-9a0f-144842bfc306"},
{"type":"match","id":"5b357cd1-35fe-4859-a2d7-48f263120bbd"}
]
}
""".data(using:.utf8)!
do {
let mtches = try decoder.decode(Matches.self, from:mtchsData)
print(mtches)
} catch {
print(error)
}
將顯示以下錯誤:
"dataCorrupted(Swift.DecodingError.Context(codingPath: [],
debugDescription: "The given data was not valid JSON.",
underlyingError: Optional(Error Domain=NSCocoaErrorDomain Code=3840
"Badly formed array around character 233."
UserInfo={NSDebugDescription=Badly
formed array around character 233.})))\n"
這是一個小錯誤,您在data
Array
第3行上缺少逗號。 添加所有內容都可以順利進行,但是如果您的服務中出現這種情況,則必須先對其進行修復。
我想您已經知道了,並且知道了逐步構建結構的方法。 在頂層,您會注意到頂層結構超出了Player
數組,實際上,這是一個Dictionary
以"data"
為唯一鍵,正如您在PlayerResponse
正確建模的那樣,正如@AnkitJayaswal所指出的那樣。 那已經造成了兩個錯誤,這些是我很容易發現的錯誤,但是正如我在繼續構建測試之前所建議的那樣,您將知道“較低”級別可以正確解析,並且可以專注於該問題。手。
以上所有內容在Playground中均可輕松實現,並且無需在此過程中實際調用WebService。 當然,您將必須import Cocoa
,但是您已經知道這一點。 無論如何,通過將問題分解成更小的部分,它總是有助於降低復雜性。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.