【问题标题】:Dynamic (But known as another key value) JSON Decoding with Swift Decodable使用 Swift Decodable 进行动态(但称为另一个键值)JSON 解码
【发布时间】:2019-08-17 02:04:45
【问题描述】:

我查看了类似问题的答案,我无法很好地理解codingKey,此外它并不完全适用于我的情况,因为密钥并非完全“未知”,它是前一个密钥的值. 我的 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 the codingkey answer do 或它们如何应用在这里,谢谢。

【问题讨论】:

    标签: json swift


    【解决方案1】:

    一个简单的解决方案是将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:) 方法。

    【讨论】:

    • 谢谢 [String:Lineup] 成功了,我可以像这样访问阵容对象子项:swift let testParameter = self.matchData.fixtures[0].lineups let homeTeamName = self.matchData.fixtures[0].homeTeam?.team_name let homeFormation = testParameter![homeTeamName!]?.formation dump(homeFormation) json ▿ Optional("4-2-3-1") - some: "4-2-3-1"
    猜你喜欢
    • 2019-10-27
    • 2021-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-10
    • 2019-07-24
    • 2019-03-13
    相关资源
    最近更新 更多