json - 使用 Codable 解析嵌套的 JSON,如 ObjectMapper Swift 4

标签 json swift codable decodable

我有一个 JSON 字符串,我想像使用 Codable 协议(protocol)的 ObjectMapper 一样解析它。

    struct Health: Mappable {
    var size: [String : Any] = [:]?
    var name: Double?

    init?(map: Map) {

    }

    mutating func mapping(map: Map) {
        size    <- map["health.size"]
        name    <- map["health.name"]
    }
}

我想消除具有直接访问权限的健康结构模型,因为为不同的属性创建每个模型结构。

let jsonString = """
 {
    "health": {
        "size":{
            "width":150,
            "height":150
            },
        "name":"Apple"
        }
 }
 """ 

我想访问带有 (.) 点运算符的属性,例如 health.size 而无需创建健康结构模型。

struct HealthType: Codable {
    var health: Health
 }

struct Health: Codable {
        var title: String
        var size: Size

        enum CodingKeys: String, CodingKey
        {
            case title = "name"
        }
     }

     struct Size: Codable {
        var width: Double
        var height: Double
     }

最佳答案

为此,您需要自己实现Codable 协议(protocol)。这并不难:

在 Playground 上尝试以下操作。

import Foundation

struct HealthType: Codable {
    let title: String
    let width: Double
    let height: Double

    enum CodingKeys: String, CodingKey
    {
        case health = "health"
        case title = "name"
        case width = "width"
        case height = "height"
        case size = "size"
    }
}

extension HealthType {

    init(from decoder: Decoder) throws {
        let healthTypeContainer = try decoder.container(keyedBy: CodingKeys.self)
        let health = try healthTypeContainer.nestedContainer(keyedBy: CodingKeys.self, forKey: .health)
        let size = try health.nestedContainer(keyedBy: CodingKeys.self, forKey: .size)
        let title = try health.decode(String.self, forKey: .title)
        let width = try size.decode(Double.self, forKey: .width)
        let height = try size.decode(Double.self, forKey: .height)
        self.init(title: title, width: width, height: height)
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        var health = container.nestedContainer(keyedBy: CodingKeys.self, forKey: .health)
        var size = health.nestedContainer(keyedBy: CodingKeys.self, forKey: .size)
        try health.encode(title, forKey: .title)
        try size.encode(width, forKey: .width)
        try size.encode(height, forKey: .height)
    }
}

let jsonData = """
{
"health": {
    "size":{
        "width":150,
        "height":150
    },
    "name":"Apple"
}
}
""".data(using: .utf8)!
do {
    print(jsonData)
    let healthType = try JSONDecoder().decode(HealthType.self, from: jsonData)
    print(healthType.title)  // Apple
    print(healthType.width)  // 150.0
    print(healthType.width)  // 150.0
} catch {
    print(error)
}

关于json - 使用 Codable 解析嵌套的 JSON,如 ObjectMapper Swift 4,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50502599/

相关文章:

php - java.lang.String 类型的值无法转换为 JSONArray

ios - swift 3 中的 uitextfield 不保存

ios - 无法在 Firebase 项目设置中添加团队 ID

ios - 解析 JSON iOS-Swift

javascript - 如何传递内联 JSON 而不是 URL 路径

javascript - json 加载为 javascript 代码并使用变量

ios - 在 Swift 3.0 iOS 中隐藏 UIPageViewController 的状态栏

swift - 如何使用 Swift 的 Codable 编码成字典?

ios - 无法将类型 '[String : Any]' 的值转换为预期的参数类型 'String'

c# - JsonConvert.DeserializeObject() 抛出 StackOverflow 异常