我正在编写一个程序来解析包含数组数组的JSON
数据,其中嵌套数组具有不同的对象类型(具体来说,[[String,String,Int]] )。例如,
{
"number": 5295,
"bets": [
[
"16",
"83",
9
],
[
"75",
"99",
4
],
[
"46",
"27",
5
]
]
}
我试图使用可编码来帮助我解析数据,但当我尝试类似
时struct OrderBook: Codable {
let number: Int
let bets: [Bet]
}
struct Bet: Codable {
let price: String
let sale: String
let quantity: Int
}
它让我错误地说
预计会解码字典
<String, Any>
,但会找到一个数组
我如何解决这个问题?我无法声明一个空类型的数组。
答案 0 :(得分:3)
正如您已经注意到[[Any]]
不符合Decodable
协议,因此您需要使用JSONSerialization
jsonObject(with: Data)
方法为您创建自定义初始值设定项结构:
struct OrderBook {
let number: Int
let bets: [Bet]
init(data: Data) throws {
let dict = try JSONSerialization.jsonObject(with: data) as? [String: Any] ?? [:]
number = dict["number"] as! Int
bets = (dict["bets"] as! [[Any]]).map {
Bet(price: $0[0] as! String, sale: $0[1] as! String, quantity: $0[2] as! Int)
}
}
}
struct Bet {
let price: String
let sale: String
let quantity: Int
}
测试:
let json = """
{"number": 5295,
"bets": [
["16","83",9],
["75","99",4],
["46","27",5]
]
}
"""
let data = Data(json.utf8)
do {
let orderBook = try OrderBook(data: data)
print(orderBook)
} catch {
print(error)
}
这将打印
订购簿(编号:5295,投注:[投注(价格:&#34; 16&#34;,销售:&#34; 83&#34;,数量: 9),投注(价格:&#34; 75&#34;,销售:&#34; 99&#34;,数量:4),投注(价格:&#34; 46&#34;,销售: &#34; 27&#34;,数量:5)])
答案 1 :(得分:3)
一种解决方案(假设您无法更改JSON)是为Bet
实现自定义解码逻辑。您可以使用未加密的容器(从JSON数组中读取)以依次解码每个属性(您调用decode(_:)
的顺序是它们预期在数组中出现的顺序)。
import Foundation
struct OrderBook : Codable {
let number: Int
let bets: [Bet]
}
struct Bet : Codable {
let price: String
let sale: String
let quantity: Int
init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
self.price = try container.decode(String.self)
self.sale = try container.decode(String.self)
self.quantity = try container.decode(Int.self)
}
// if you need encoding (if not, make Bet Decodable
// and remove this method)
func encode(to encoder: Encoder) throws {
var container = encoder.unkeyedContainer()
try container.encode(price)
try container.encode(sale)
try container.encode(quantity)
}
}
解码示例:
let jsonString = """
{ "number": 5295, "bets": [["16","83",9], ["75","99",4], ["46","27",5]] }
"""
let jsonData = Data(jsonString.utf8)
do {
let decoded = try JSONDecoder().decode(OrderBook.self, from: jsonData)
print(decoded)
} catch {
print(error)
}
// OrderBook(number: 5295, bets: [
// Bet(price: "16", sale: "83", quantity: 9),
// Bet(price: "75", sale: "99", quantity: 4),
// Bet(price: "46", sale: "27", quantity: 5)
// ])
答案 2 :(得分:-1)
这是糟糕的json结构,如果你可以从服务器上改变它,我建议:
SwiftyJSON
但是如果你不能改变那种json格式,我认为你应该使用Codable
库来处理json。我讨厌{{1}}:)