默认情况下,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/