Разбор JSON с использованием codable и игнорированием первого уровня JSON

У меня такой 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. Как лучше всего это сделать?

Меня смущает игнорирование ключей "success" и "message" в первом ответе JSON и переход сразу к значению ключа "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)")

}

person Nevin Jethmalani    schedule 19.12.2017    source источник
comment
Обратите внимание, что Swift - это язык с предполагаемым типом return bid ?? buy ?? [], а catch let error является избыточным только catch   -  person Leo Dabus    schedule 19.12.2017


Ответы (1)


Чтобы ответить на ваши вопросы напрямую, да, очень легко игнорировать пары "ключ-значение" success и message и сразу перейти к results.

Несмотря на это, будет немного сложно иметь единую структуру для анализа обоих этих ответов JSON. Оба они имеют совершенно разную структуру, что упрощает использование двух разных структур для кодирования. Чтобы выделить некоторые различия:

  1. buy, sell вложены внутрь results. bids, asks нет.
  2. Ключи совершенно разные.
  3. buy, sell имеют массив пар "ключ-значение", а bids, asks simple имеют массив значений.

Кодируемые структуры должны быть простыми и понятными. Лучше, чтобы каждому ответу соответствовало два.

person NSAdi    schedule 19.12.2017
comment
идеально. Должен ли я, как только я получу эти два, превратить их в одно? Как игнорировать пары ключ-значение "успех" и "сообщение"? - person Nevin Jethmalani; 19.12.2017
comment
Я бы рекомендовал иметь разные структуры для их кодирования. Вам не нужно игнорировать никакие ключи. Просто проанализируйте те ключи, которые вам нужны, и не беспокойтесь об остальном. - person NSAdi; 19.12.2017
comment
но я не хочу иметь структуру только со значением result. разве это не бессмысленно? Невозможно сразу перейти к значениям в ключе result. - person Nevin Jethmalani; 19.12.2017
comment
Ваш код уже делает это. Мой ответ - решить ваш конкретный вопрос о наличии двух разных структур. Если вам нужно руководство по JSON в Swift 4, то вот одно ... benscheirman.com/2017/06/swift-json - person NSAdi; 19.12.2017
comment
Я уже просмотрел это руководство. Это потрясающе. Но я все еще не мог понять, как игнорировать этот успех и сообщение, не создав новую структуру для их анализа. Нет возможности это сделать при декодировании? Я добавил к своему ответу, чтобы показать вам, как я делаю декодирование - person Nevin Jethmalani; 19.12.2017