I've looked at the answer of the similar question I could not understand the codingKey very well in addition it doesn't exactly apply to my case as the key is not completely "unknown" it is the value of a previous key. My Api:
{
"api": {
"results": 1,
"fixtures": [
{
"homeTeam": {
"team_name": "Tottenham"
},
"awayTeam": {
"team_name": "Everton"
},
"lineups": {
"Tottenham": {
"formation": "4-2-3-1"
},
"Everton": {
"formation": "4-2-3-1"
}
}
}
]
}
}
My Code:
class matchApiObject: Decodable
{
let fixtures: [fixture]
init (fixtures: [fixture])
{
self.fixtures = fixtures
}
}
class fixture: Decodable
{
let homeTeam: matchHomeTeamObject?
let lineups: lineUpsObject?
init (homeTeam: matchHomeTeamObject?, lineups: lineUpsObject?)
{
self.homeTeam = homeTeam
self.lineups = lineups
}
}
class matchHomeTeamObject: Decodable
{
let team_name: String?
init (team_name: String?)
{
self.team_name = team_name
}
}
class lineUpsObject: Decodable
{
struct homeLineUp: Decodable
{
let formation: String?
init(formation: String?)
{
self.formation = formation
}
}
struct awayLineUp: Decodable
{
let formation: String?
init (formation: String?)
{
self.formation = formation
}
}
}
Obviously the keys of the lineups objects won't be "homeLineUp" but it will be as per the api example, the value of the homeTeam.team_name.
So what I imagine the solution to be is:
class lineUpsObject: Decodable
{
struct homeTeam.team_name: Decodable
{
let formation: String?
init(formation: String?)
{
self.formation = formation
}
}
struct awayTeam.team_name: Decodable
{
let formation: String?
init (formation: String?)
{
self.formation = formation
}
}
}
Which is not possible, I know I have to use a codingkey for this, but I can't understand how to declare the name of the key to be the value of a previous key value I did not understand what stringValue: String or intValue: Int do in the codingkey answer do or how they apply here, thank you.
A simple solution is to decode lineups
as dictionary, I named all structs with starting capital letter to conform to the naming convention.
The init
methods are not needed
struct Root : Decodable {
let api : API
}
struct API : Decodable {
let results : Int
let fixtures : [Fixture]
}
struct Fixture : Decodable {
let homeTeam, awayTeam: Team
let lineups : [String:Lineup]
}
struct Team : Decodable {
let teamName : String
}
struct Lineup : Decodable {
let formation : String
}
To convert the snake_cased keys to camelCased struct members add the appropriate strategy
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
A more sophisticated solution is to put the formation
data into the Team
struct but this requires to implement the init(from decoder:)
method in Fixture
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.