[英]Swift Decodable: how to transform one of values during decoding?
默认情况下, Decodable
协议将 JSON 值转换为 object 值,没有任何变化。 但有时您需要在 json 解码期间转换值,例如,在 JSON 中您得到{id = "id10"}
但在您的 class 实例中您需要将数字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:)
的情况下,我应该为我班级的 20 个字段中的每一个字段手动获取和放置值! 经过多年的 objC 编码,我很直观地首先调用 super 的init(from:)
实现,然后仅对某些字段进行更改,但我如何使用 Swift 和Decodable
协议实现这样的效果?
你可以使用lazy var
。 缺点是你仍然需要提供一个键列表,你不能声明你的模型是一个常量:
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)
当前,如果您想要更改甚至单个属性的解析,则必须完全实现encode
和decode
方法。
Swift Codable 的某些未来版本可能会允许逐个处理每个属性的编码和解码。 但是 Swift 功能工作非常重要,尚未确定优先级:
无论如何,我们的目标是可能提供一种强类型的解决方案,允许您根据具体情况执行此操作,而不会掉下“悬崖”而不得不实施所有
encode(to:
和init(from:
为了一个财产的利益;解决方案可能很重要,需要大量 API 讨论才能弄清楚如何做好,因此我们还不能做到这一点。- Itai Ferber,Swift 4 Codable 的首席开发人员
https://bugs.swift.org/browse/SR-5249?focusedCommentId=32638
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.