基本上,我有一个返回如下内容的api:
"order_detail": [
{
"id": 6938,
"order_id": 6404,
"item_price": "4",
..
"item": {
"id": 12644,
"ref": "Iced Caffe Americano",
"short_description": "",
..
在可解码的obj中,我得到了
public struct OrderDetail: Decodable {
public let id: Int
public let order_id: Int
public let item_price: String?
..
public let item: Item?
和
public struct Item: Decodable {
public var id: Int
public var ref: String?
public var short_description: String?
问题在于代码中的其他地方,有一种方法期望Item对象具有item_price
。
我想要做的是混淆或更改此常量Item对象,并向其动态添加item_price
属性。我该怎么做?
我知道针对同一问题还有很多其他解决方案(正如我们所说的,我正在研究它,只是简单地修改api端点以满足我的需要)。但是同样,该选项并非总是可行的(即,假设后端团队是独立的)
这也是可能的,但也不便宜,因为此功能在应用程序中许多其他我无法控制的地方都使用了
答案 0 :(得分:2)
如果要向不属于其JSON表示形式的Decodable
类型添加属性,则只需声明一个CodingKey
一致类型并省略特定的属性名称,以便自动合成的init(from decoder:Decoder)
初始化程序将知道不要在JSON中查找该值。
此外,您还应该遵守Swift命名约定(lowerCamelCase表示变量名),并使用CodingKey
将JSON键映射到属性名。
public struct Item: Decodable {
public var id: Int
public var ref: String?
public var shortDescription: String?
public var itemPrice: String? // or whatever else its type needs to be
private enum CodingKeys: String, CodingKey {
case id, ref, shortDescription = "short_description"
}
}
答案 1 :(得分:0)
这是实现这一目标的一种方法
接管Item
在OrderDetail解码中的初始化。
struct OrderDetail: Decodable {
let id: Int
let orderId: Int
let itemPrice: String?
let item: Item
private enum OrderDetailCodingKey: CodingKey {
case id
case orderId
case itemPrice
case item
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: OrderDetailCodingKey.self)
self.id = try container.decode(Int.self, forKey: .id)
self.orderId = try container.decode(Int.self, forKey: .orderId)
let itemPrice = try container.decode(String?.self, forKey: .itemPrice)
self.itemPrice = itemPrice
self.item = try Item(from: decoder, itemPrice: itemPrice)
}
}
使用自定义初始化程序创建您的商品。
struct Item: Decodable {
let id: Int
let ref: String?
let shortDescription: String?
let itemPrice: String?
private enum ItemCodingKeys: CodingKey {
case id
case ref
case shortDescription
}
init(from decoder: Decoder, itemPrice: String?) throws {
let container = try decoder.container(keyedBy: ItemCodingKeys.self)
self.id = try container.decode(Int.self, forKey: .id)
self.ref = try? container.decode(String.self, forKey: .ref)
self.shortDescription = try? container.decode(String.self, forKey: .shortDescription)
self.itemPrice = itemPrice
}
}
您可以调用以下函数来测试该功能:
private func test() {
let json = """
{"id":6938,"orderId":6404,"itemPrice":"4","item":{"id":12644,"ref":"Iced Caffe Americano","shortDescription":""}}
"""
let data = json.data(using: .utf8)
let decoder = JSONDecoder()
if let data = data {
do {
let order = try decoder.decode(OrderDetail.self, from: data)
print(order)
} catch let jsonError {
os_log("JSON decoding failed [%@]", String(describing: jsonError))
}
} else {
os_log("No data found")
}
}