我有一个 json 数据,它由 rest api 以
‘split’ : dict like {‘index’ -> [index], ‘columns’ -> [columns], ‘data’ -> [values]}
这是使用 Python 中的pandas.to_json(orient=‘split’)
生成的
我想将其解码为一个快速的对象。我尝试使用可解码,但我不知道如何将列位置动态分配给对象
示例数据:
{
"columns":
["cprcode","iprcode","psqty"],
"index":
[0,3,4,5,6,11],
"data":
[
[123,"abc",123],
[424, "ads",145],
[63, "hrw",475],
[8685, "gds",848],
[754, "ah",659],
[374, "rh",597],
]
}
我希望输出在 for 中[Product]
哪里
struct Product{
let cprcode: Int
let iprcode: String
let psqty: Int
}
我试过了
使用这样的自定义数组类进行解码,但我不确定如何将它们拆分为产品对象。请注意,列是动态的,因此对数据中的列顺序进行硬编码是有风险的。
class ProductDF:Codable{
let columns:[String]
let index:[Int]
let data:[[Product]]
}
这可以通过自定义init(from:)
来完成,我们使用嵌套容器从"数据"中提取产品对象。
由于"data"下的每个子数组都是一个产品,因此我们对声明进行了一些更改
struct ProductDF: Codable {
let columns: [String]
let index: [Int]
let data: [Product]
}
为了简化代码,我们为列创建了一个枚举
enum DataColumn: String {
case cprcode, iprcode, psqty
}
然后是我们添加到ProductDF
的init(from:)
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
columns = try container.decode([String].self, forKey: .columns)
index = try container.decode([Int].self, forKey: .index)
var dataContainer = try container.nestedUnkeyedContainer(forKey: .data)
var products = [Product]()
while !dataContainer.isAtEnd {
var array = try dataContainer.nestedUnkeyedContainer()
var cprCode = 0
var iprCode = ""
var psQty = 0
for column in columns {
switch DataColumn(rawValue: column) {
case .cprcode:
cprCode = try array.decode(Int.self)
case .iprcode:
iprCode = try array.decode(String.self)
case .psqty:
psQty = try array.decode(Int.self)
case .none:
fatalError()
}
}
let product = Product(cprcode: cprCode, iprcode: iprCode, psqty: psQty)
products.append(product)
}
data = products
}
这应该完成基本工作,尽管我建议通过抛出错误而不是使用fatalError
来改进错误处理,并检查是否已将某些内容分配给while
循环中的所有 3 个变量,例如将它们设为可选并在创建Product
之前验证所有变量都不是 nil