Swift Codable with Different Array Types

霸气de小男生 提交于 2019-12-01 06:04:16

问题


I'm writing a program where I'm parsing JSON data that includes array of arrays, where the nested arrays have different object types (specifically, [[String, String, Int]]). For example,

{
"number": 5295,
"bets": [
    [
        "16",
        "83",
        9
    ],
    [
        "75",
        "99",
        4
    ],
    [
        "46",
        "27",
        5
    ]
]
}

I'm trying to use codable to help me parse the data, but when I try something like

struct OrderBook: Codable {
    let number: Int
    let bets: [Bet]
}

struct Bet: Codable {
    let price: String
    let sale: String
    let quantity: Int
}

it gives me errors saying that

Expected to decode Dictionary<String, Any> but found an array instead

How do I get around this? I can't declare an array of empty type.


回答1:


Please check Hamish post bellow https://stackoverflow.com/a/48014394/2303865




回答2:


One solution (assuming you can't change the JSON) is to implement custom decoding logic for Bet. You can use an unkeyed container (which reads from a JSON array) in order to decode each of the properties in turn (the order in which you call decode(_:) is the order they're expected to appear in the array).

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)
  }
}

Example decoding:

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)
// ])


来源:https://stackoverflow.com/questions/48002429/swift-codable-with-different-array-types

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!