【问题标题】:Parsing JSON using codable and ignoring first layer of JSON使用可编码并忽略 JSON 的第一层解析 JSON
【发布时间】:2017-12-19 01:25:58
【问题描述】:

我有这样的 JSON:

{
"success": true,
"message": "",
"result": {
    "buy": [
        {
            "Quantity": 0.0056,
            "Rate": 18527
        },
        {
            "Quantity": 0.11431426,
            "Rate": 18526
        }
    ], 
    "sell":[
        {
            "Quantity": 8.20604116,
            "Rate": 18540
        },
        {
            "Quantity": 0.95600491,
            "Rate": 18574.99999998
        }
    ]
  }
}

还有一组这样的 JSON:

{
      "lastUpdateId": 1027024,
      "bids": [
        [
          "4.00000000",     // PRICE
          "431.00000000",   // QTY
          []                // Can be ignored
        ]
      ],
      "asks": [
        [
          "4.00000200",
          "12.00000000",
          []
        ]
      ]
    }

使用 codable 解析这两个响应的最佳方法是什么?它们都需要使用相同的结构进行解析,或者需要转换为相同的结构(无论哪种方式都能更快地完成工作)。我不想为整个第一个响应创建一个结构,因为我不会使用像 "success""message" 这样的键。我基本上想忽略这些并直接访问"result" 键但是在第二个响应中,我将使用所有数据,因此我创建了一个名为TotalOrderBook 的结构。做这个的最好方式是什么?

让我感到困惑的是忽略第一个 JSON 响应中的键 "success""message" 并直接获取键 "result" 的值。是否可以在不创建额外结构的情况下做到这一点?

这就是我现在所拥有的。我想避免添加另一个结构,因为我真正需要的是买/卖和卖/卖下的值。

struct TotalOrderBook:Codable{
    var buy:[UniversalOrder]?
    var sell:[UniversalOrder]?

    var bid:[UniversalOrder]?
    var ask:[UniversalOrder]?

    var buyOrderBook: [UniversalOrder] {
        return bid ?? buy ?? [UniversalOrder]()
    }
    var sellOrderBook: [UniversalOrder] {
        return ask ?? sell ?? [UniversalOrder]()
    }

    var updatedTime:Date
}


struct UniversalOrder:Codable{
    var price : Double {
        return Double(rate ?? binPrice ?? 0)
    }

    var size : Double {
        return Double(quantity ?? binQuantity ?? 0 )
    }
    //let numOrders : Int

    var quantity:Double?
    var rate:Double?

    var binPrice:Double?
    var binQuantity:Double?

    private enum CodingKeys: String, CodingKey {
        case rate = "Rate"
        case quantity = "Quantity"
        //case numOrders, binPrice,
    }

    init(from decoder: Decoder) throws {
        var container = try decoder.unkeyedContainer()
        binPrice = Double(try container.decode(String.self)) ?? nil
        binQuantity = Double(try container.decode(String.self))  ?? nil
        quantity = nil
        rate = nil
    }
}

这就是我的解码方式:

let decoder = JSONDecoder()
let data = try! JSONSerialization.data(withJSONObject: value) //value is the response from Alamofire

var theWholeOrderBook:UniversalOrder!
do {
    theWholeOrderBook = try decoder.decode(UniversalOrder.self, from: data)
} catch let error {
    //print ("error is \(e) ** \(value)")

}

【问题讨论】:

  • 请注意,Swift 是一种类型推断语言 return bid ?? buy ?? []catch let error 是多余的,只是 catch

标签: json swift swift4 codable


【解决方案1】:

要直接回答您的问题,是的,很容易忽略 successmessage 键值对并直接访问 results

尽管如此,使用单个结构来解析这两个 JSON 响应会有点复杂。 它们都具有非常不同的结构,这将使使用两个不同的结构来使用编码变得更加容易。突出一些差异:

  1. buysell 嵌套在 results 中。 bidsasks 不是。
  2. 键完全不同。
  3. buysell 有一个键值对数组,而bidsasks simple 有一个值数组。

可编码结构应该简单明了。最好有两个对应于每个响应。

【讨论】:

  • 完美。一旦我得到这两个,我应该将它们转换为一个吗?如何忽略成功和消息键值对?
  • 我建议使用不同的结构来对它们进行编码。您不必“忽略”任何键。只需解析您想要解析的键,其余的不用操心。
  • 但我不想有一个只有 result 值的结构。那不是没有意义吗?没有办法直接获取 result 键中的值
  • 您的代码已经在这样做了。我的回答是解决你关于拥有两种不同结构的具体问题,如果你想要 Swift 4 中的 JSON 指南,那么这里有一个......benscheirman.com/2017/06/swift-json
  • 我已经看过这个指南了。这是惊人的。但是我仍然无法弄清楚如何在不创建新结构来解析它们的情况下忽略该成功和消息。解码时有没有办法做到这一点?我已添加到我的答案中,以向您展示我是如何进行解码的
猜你喜欢
  • 2017-05-26
  • 2020-02-01
  • 1970-01-01
  • 2020-02-09
  • 2021-12-31
  • 1970-01-01
  • 2020-08-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多