繁体   English   中英

使用Swift Decodable进行动态(但又称为另一个键值)JSON解码

[英]Dynamic (But known as another key value) JSON Decoding with Swift Decodable

我已经看过类似问题的答案,但我对它的编码非常了解,因为它并不是完全“未知”的,因为它不是前一个键的值,因此它不适用于我的情况。 我的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"
          }
        }
      }
    ]
  }
}

我的代码:

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
        }
    }
}

显然,阵容对象的键不是“ homeLineUp”,而是按照api示例,即homeTeam.team_name的值。

所以我想象的解决方案是:

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
        }
    }
}

这是不可能的,我知道我必须为此使用编码键,但是我不明白如何将键的名称声明为前一个键值的值,但我不理解是什么stringValue:String或intValue: int do in codekey回答do或它们在这里如何应用,谢谢。

一个简单的解决方案是将lineups解码为字典,我用起始大写字母命名所有结构以符合命名约定。

不需要init方法

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
}

要将snake_cased键转换为camelCased结构成员,请添加适当的策略

let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase

一个更复杂的解决方案是将formation数据放入Team结构中,但这需要在Fixture实现init(from decoder:)方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM