Swift: печать переменной с разными типами (enum) из JSON в цикле for - PullRequest
0 голосов
/ 08 марта 2019

Ситуация такова: Как декодировать свойство JSON с разными типами?

Я использовал код, помеченный как решение в связанном вопросе, и я хочу напечататьпеременная в цикле for:

struct GetEvents: Decodable{
    var id: String?
    var expansion: String?
    var distance: Distance?
}

enum Distance: Codable {
    case int(Int)
    case string(String)

    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        switch self {
        case .int(let v): try container.encode(v)
        case .string(let v): try container.encode(v)
        }
    }

    init(from decoder: Decoder) throws {
        let value = try decoder.singleValueContainer()
        do {
            self = .int(try value.decode(Int.self))
        } catch DecodingError.typeMismatch {
            self = .string(try value.decode(String.self))
        }
    }

    enum ParseError: Error {
        case notRecognizedType(Any)
    }
}

Я пытаюсь напечатать все переменные в цикле for, потому что у меня несколько объектов внутри объекта.

for i in 0...(getEventsText.items.count - 1) {
                    if let idAsString = getEventsText.items[i].id {
                        print(idAsString)
                    }
                    if let distanceAsString = getEventsText.items[i].distance {
                        print(distanceAsString)
                    }
                    if let epansionAsString = getEventsText.items[i].offer_expansion {
                        print(expansionAsString)
                    }

Я получаю идентификатор ирасширение, но расстояние отображается как int (-1), а не как -1

Если я просто выведу его так, как это:

for x in range getEventsText.items {
    print(x)
}

Возвращает

GetEvents(id: необязательно ("7576"), расстояние: Swift.ImplicitlyUnwrappedOptional.some (DB_Read_enums_Test1.Distance.int (0)), расширение: необязательно ("0"))

1 Ответ

1 голос
/ 08 марта 2019

Позвольте Distance реализовать CustomStringConvertible и добавить следующее

var description: String {
    switch self {
        case let .int(value):
            return "\(value)"
        case let .string(value):            
            return value
    }
}

enum Distance: Codable, CustomStringConvertible {
    case int(Int)
    case string(String)

    var description: String {
        switch self {
        case let .int(value):
            return "\(value)"
        case let .string(value):            
            return value
    }

    //rest of code
}

Контрольный пример

let data = """
    {"id": "7576", "expansion": "0", "distance": -1}
    """.data(using: .utf8)!

do {
    let decoder = JSONDecoder()

    let result = try decoder.decode(GetEvents.self, from: data)
    print(String(describing: result.id))
    print(String(describing: result.expansion))
    print(String(describing: result.distance))    
} catch {
    print(error)
}

вывод равен

Optional("7576")
Optional("0")
Optional(-1)

и если я изменю свой json на "..." distance ":" long "}, то последняя строка вывода изменится на

Optional(long)
...