使用可编码并忽略 JSON 的第一层解析 JSON

Posted

技术标签:

【中文标题】使用可编码并忽略 JSON 的第一层解析 JSON【英文标题】:Parsing JSON using codable and ignoring first layer of 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 【参考方案1】:

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

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

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

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

【讨论】:

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

以上是关于使用可编码并忽略 JSON 的第一层解析 JSON的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Kotlin 序列化解析 JSON 对象列表中的第一个属性?

仅在 Json Swift 3 中附加数组的第一项

json数据解析重要的一点

使用 Codable 解析 JSON 数据

在 JSON.NET 数据解析期间忽略解析错误

如何忽略 JSON 解析回数据中的某些对象?