简体   繁体   English

在 Swift 中使用 Codable 进行解析

[英]Parse using Codable in Swift

Need to parse this JSON in such a way that i should be able to access the benefits associated to each plan inside the "enabled" key within "items" node as below:需要以这样一种方式解析这个 JSON,以便我应该能够访问与“项目”节点中“启用”键内的每个计划相关的好处,如下所示:

let items = Items[0].plans.main[0].enabled[0].text让 items = Items[0].plans.main[0].enabled[0].text

{
  "MyData": {
    "data": {
      "benefits": {
        "B1": {
          "text": "Text1"
        },
        "B2": {
          "text": "Text2"
        },
        "B3": {
          "text": "text3"
        }
      }
    },
    "items": [
      {
        "plans": {
          "main": [
            {
              "name": "plan1",
              "enabled": [
                "B1",
                "B2"
              ],
              "disabled": [
                "B2",
                "B3"
              ]
            }
          ]
        }
      }
    ]
  }
}

I have tried as below to achieve but seems like this is not working我已经尝试如下实现,但似乎这不起作用

class Main: Codable {
    
    var name: String?
    
    var enabled: [String]?
    var disabled: [String]?
    
    enum CodingKeys: String, CodingKey {
        case name = "name"
        case enabled = "enabled"
        case disabled = "disabled"
    }

class MyData: Codable {
    var benefits: [String: Benefit]?
    
    enum CodingKeys: String, CodingKey {
        case benefits = "benefits"
    }
    
    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        let propertyContainer = try container.nestedContainer(keyedBy: CustomDynamicKey.self, forKey: .benefits)
        self.benefits = propertyContainer.decodeValues()
    }

class Benefit: Codable {
    
    var text: String?
    
    enum CodingKeys: String, CodingKey {
        case text = "text"
    }
    
    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        
        text = try container.decode(String.self, forKey: .text)
    }
}

struct CustomDynamicKey: CodingKey {
    
    var stringValue: String

    init?(stringValue: String) {
        self.stringValue = stringValue
    }
    
    var intValue: Int? { return nil }
    
    init?(intValue: Int) { return nil }
    

extension KeyedDecodingContainer where Key == DynamicKey {
    
    func decodeValues() -> [String : Benefit] {
        var dict = [String : Benefit]()
        for key in allKeys {
            if let md = try? decode(Benefit.self, forKey: key) {
                dict[key.stringValue] = md
            } else {
                print("unsupported key")
            }
        }
        return dict
    }
}

I tried to parse the models individually.我试图单独解析模型。 However, i am able to access the models separately but i need to map the corresponding the benefit with the respective plan at the time of parsing JSON itself inside the required init() methods using Manual parsing.但是,我可以单独访问模型,但我需要 map 在使用手动解析在所需的 init() 方法中解析 JSON 本身时与相应计划对应的好处。

One way could be to use JSONDecoder alongside JSONSerialization .一种方法是使用JSONDecoderJSONSerialization Codables are a bit uncomfortable to use in such situations, and you can make var benefits: [String: Benefit]? Codables在这种情况下使用起来有点不舒服,你可以让var benefits: [String: Benefit]? optional (which you already have) and remove it from the CodingKeys enum.可选(您已经拥有)并将其从CodingKeys枚举中删除。 Then, use JSONSerialization to get the benefits field filled.然后,使用JSONSerialization填充benefits字段。

See This看到这个

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

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