ios - Swift 可解码 : how to transform one of values during decoding?

标签 ios json swift decoder codable

默认情况下,Decodable 协议(protocol)将 JSON 值转换为对象值而无需更改。但有时你需要在 json 解码期间转换值,例如,在 JSON 中你得到 {id = "id10"} 但在你的类实例中你需要输入数字 10进入属性 id(或者甚至进入具有不同名称的属性)。

您可以实现方法 init(from:),您可以在其中使用任何值执行您想要的操作,例如:

public required init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    latitude = try container.decode(Double.self, forKey:.latitude)
    longitude = try container.decode(Double.self, forKey: .longitude)
    // and for example there i can transform string "id10" to number 10
    // and put it into desired field
}

这对我来说听起来不错,但是如果我想仅更改一个 JSON 字段的值,而让其他 20 个字段保持不变怎么办?在 init(from:) 的情况下,我应该为类(class)的 20 个字段中的每一个字段手动获取和放置值!经过多年的 objC 编码,我很直观地首先调用 super 的 init(from:) 实现,然后仅对某些字段进行更改,但我如何使用 Swift 和 Decodable 实现这种效果 协议(protocol)?

最佳答案

您可以使用惰性变量。缺点是您仍然必须提供键列表,并且不能将模型声明为常量:

struct MyModel: Decodable {
    lazy var id: Int = {
        return Int(_id.replacingOccurrences(of: "id", with: ""))!
    }()
    private var _id: String

    var latitude: CGFloat
    var longitude: CGFloat

    enum CodingKeys: String, CodingKey {
        case latitude, longitude
        case _id = "id"
    }
}

例子:

let json = """
{
    "id": "id10",
    "latitude": 1,
    "longitude": 1
}
""".data(using: .utf8)!

// Can't use a `let` here
var m = try JSONDecoder().decode(MyModel.self, from: json)
print(m.id)

关于ios - Swift 可解码 : how to transform one of values during decoding?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45429960/

相关文章:

iphone - 对某些类使用类别,而不是对完整代码使用类别

ios - 自定义 Facebook 登录 View Swift

ios - xcode 更改包标识符以覆盖旧应用程序

iphone - AVplayer 2-3 次后未在 ScrollView 中显示

Javascript - 访问 JSON 对象数组

javascript - 使用 php 将数组转换为 json,并使用 jquery 或 javascript 检索 json

ios - 数据下载完成后如何重新加载 uipageviewcontroller 以考虑新数据。 swift 3

javascript - 使用 Controller js 代码中的分层 json 对象应用 Angular Filter

ios - Firebase 找不到 'module <Firebase>'

ios - 收藏查看项目大小和数量