JSON не декодируется в структуру (фатальная ошибка, Swift) - PullRequest
0 голосов
/ 23 июня 2018

Я пытаюсь декодировать следующий ответ JSON:

{"success":true,"initialprice":"0.00003592","price":"0.00006587",
"high":"0.00006599","low":"0.00003499","volume":"0.68979910",
"bid":"0.00006205","ask":"0.00006595"}

В структуру в Swift, которая выглядит следующим образом:

struct TOTicker : Codable {
public var success : Bool?
public var initialprice : Double?
public var price : Double?
public var high : Double?
public var low : Double?
public var volume :Double?
public var bid :Double?
public var ask :Double?
}

Строка кода, которую я использую для декодированиявыглядит следующим образом:

let decoder = JSONDecoder()
let ticker = try! decoder.decode(TOTicker.self, from: jsonData)

И он продолжает выдавать роковую ошибку, но я понятия не имею, почему.Я использовал этот метод для декодирования раньше без проблем.

Ответы [ 3 ]

0 голосов
/ 23 июня 2018

Во-первых, чтобы узнать причину ошибки, вы должны сделать блок do-catch вместо try!:

do {
    let ticker = try decoder.decode(TOTicker.self, from: jsonData)
} catch {
    print(error)
}

Следовательно, вы заметите, что ошибка:

typeMismatch (Swift.Double, Swift.DecodingError.Context (codingPath: [CodingKeys (stringValue: «initialprice», intValue: nil)], debugDescription: "Ожидается декодировать Double, но найдена строка / данные вместо. ", underError: nil))

, который кажется достаточно ясным; Ваш json содержит строки в качестве значений вместо двойных (значения с плавающей запятой заключены в ""). Что вы должны сделать, это объявить TOTicker свойства как:

struct TOTicker : Codable {
    public var success : Bool?
    public var initialprice : String?
    public var price : String?
    public var high : String?
    public var low : String?
    public var volume :String?
    public var bid :String?
    public var ask :String?
}

Теперь вы заметите, что можете успешно его проанализировать:

let decoder = JSONDecoder()

do {
    let ticker = try decoder.decode(TOTicker.self, from: jsonData)
    print(ticker)
} catch {
    print(error)
}

Вы должны увидеть в журнале:

TOTicker (успех: необязательный (true), начальная цена: Опционально («0,00003592»), цена: опционально («0,00006587»), высокая: Необязательно («0,00006599»), низкий: Необязательно («0,00003499»), объем: Необязательно ("0,68979910"), ставка: Необязательно ("0,00006205"), спросите: Дополнительно ( "0,00006595"))

0 голосов
/ 24 июня 2018

Проблема, как уже сообщал @AhmadF, заключается в том, что декодер ожидает декодирования Double, но вместо этого нашел строку.Лучшим решением было бы вместо того, чтобы изменять тип свойств, это реализовать свой собственный декодер, чтобы декодировать эти строки и привести их к Double.

Примечание: Вы должны объявить свои свойства структуры как константы и только необязательные, которыесервер не может быть возвращен (api):

struct TOTicker: Codable {
    let success: Bool
    let initialprice: Double
    let price: Double
    let high: Double
    let low: Double
    let volume: Double
    let bid: Double
    let ask: Double
}

Пользовательский декодер:

extension TOTicker {
    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        guard
            let initialprice = try Double(container.decode(String.self, forKey: .initialprice)),
            let price = try Double(container.decode(String.self, forKey: .price)),
            let high = try Double(container.decode(String.self, forKey: .high)),
            let low = try Double(container.decode(String.self, forKey: .low)),
            let volume = try Double(container.decode(String.self, forKey: .volume)),
            let bid = try Double(container.decode(String.self, forKey: .bid)),
            let ask = try Double(container.decode(String.self, forKey: .ask))
        else {
            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: container.codingPath, debugDescription: "Error decoding String into Double"))
        }
        success = try container.decode(Bool.self, forKey: .success)
        self.initialprice = initialprice
        self.price = price
        self.high = high
        self.low = low
        self.volume = volume
        self.bid = bid
        self.ask = ask
    }
}

Теперь вы можете правильно декодировать свой json:

let data = Data("""
{"success":true,"initialprice":"0.00003592","price":"0.00006587",
    "high":"0.00006599","low":"0.00003499","volume":"0.68979910",
    "bid":"0.00006205","ask":"0.00006595"}
""".utf8)

let decoder = JSONDecoder()
do {
    let ticker = try decoder.decode(TOTicker.self, from: data)
    print(ticker)
} catch {
    print(error)
}

Это напечатает:

TOTicker (успех: истина, начальная цена: 3.5920000000000002e-05, цена: 6.5870000000000005e-05, высокая: 6.59899999999999999e-05, низкая: 3.4990000000000002e-05,объем: 0,6897991, ставка: 6,2050000000000004e-05, спрос: 6,5950000000000004e-05)

0 голосов
/ 23 июня 2018

Все значения являются строками (отмечены "", а не содержимым), за исключением успеха Bool

struct TOTicker : Codable {
    public var success : Bool?
    public var initialprice : String?
    public var price : String?
    public var high : String?
    public var low : String?
    public var volume :String?
    public var bid :String?
    public var ask :String?
}

//

do {
    let decoder = JSONDecoder()
    let ticker = try decoder.decode(TOTicker.self, from: jsonData)
  }
catch {
      print(error)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...