[英]Decoding JSON array with codable - Swift 5
我想解碼以下鏈接中的json數據
但是,rowSet 數據是數組內部的一組 json 數組。 如何設置可編碼結構來解碼此數據? 我能夠設置以下結構來解碼其他數據。
import Foundation
struct leagueLeader: Codable {
var resource: String
var parameters: parameters
}
struct parameters: Codable {
var LeagueID: String
var PerMode: String
var StatCategory: String
var Season: String
var SeasonType: String
}
struct resultSet: Codable {
var name: String
var headers: [String]
}
困難的部分是處理應該包含多種數據類型的rowSet
{
"rowSet": [
[
1,
1610612756,
"PHX",
"Phoenix Suns",
1987
]
]
}
解決方案是聲明一個枚舉,每個 case 都有一個表示可編碼數據類型的關聯值
enum RowSet: Codable, Equatable {
case integer(Int)
case string(String)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let x = try? container.decode(Int.self) {
self = .integer(x)
return
}
if let x = try? container.decode(String.self) {
self = .string(x)
return
}
throw DecodingError.typeMismatch(RowSet.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for RowSet"))
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .integer(let x):
try container.encode(x)
case .string(let x):
try container.encode(x)
}
}
}
型號齊全:
import Foundation
struct Leader: Codable, Equatable {
let resource: String?
let parameters: Parameters?
let resultSets: [ResultSet]?
}
struct Parameters: Codable, Equatable {
let leagueId, season, seasonType, perMode: String?
let playerOrTeam: String?
enum CodingKeys: String, CodingKey {
case leagueId = "LeagueID"
case season = "Season"
case seasonType = "SeasonType"
case perMode = "PerMode"
case playerOrTeam = "PlayerOrTeam"
}
}
struct ResultSet: Codable, Equatable {
let name: String?
let headers: [String]?
let rowSet: [[RowSet]]?
}
enum RowSet: Codable, Equatable {
case integer(Int)
case string(String)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let x = try? container.decode(Int.self) {
self = .integer(x)
return
}
if let x = try? container.decode(String.self) {
self = .string(x)
return
}
throw DecodingError.typeMismatch(RowSet.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for RowSet"))
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .integer(let x):
try container.encode(x)
case .string(let x):
try container.encode(x)
}
}
}
這種 JSON 結構非常不尋常。 它是一種逗號分隔值 (CSV),無法隱式解碼為結構體。
一個解決方案是手動解碼數組
struct RowSet: Decodable {
let rank, teamID : Int
let teamAbbreviation, teamName : String
let ast : Int
init(from decoder: Decoder) throws {
var arrayContainer = try decoder.unkeyedContainer()
guard arrayContainer.count == 5 else { throw DecodingError.dataCorruptedError(in: arrayContainer, debugDescription: "The array must contain 5 items") }
rank = try arrayContainer.decode(Int.self)
teamID = try arrayContainer.decode(Int.self)
teamAbbreviation = try arrayContainer.decode(String.self)
teamName = try arrayContainer.decode(String.self)
ast = try arrayContainer.decode(Int.self)
}
}
正如評論中提到的,請遵守命名約定:結構、類和枚舉以大寫字母開頭,變量、屬性、函數和枚舉案例以小寫字母開頭。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.