/ / Swift 4 Кодируемо: Конвертиране на JSON връщане на Intring / Date / Float - ios, json, swift, swift4

Swift 4 Codable: Преобразуване на JSON връщане на String към Int / Date / Float - ios, json, swift, swift4, кодова

Преглеждам някои проекти и премахвам JSON разбиващите фреймове, тъй като изглежда доста лесно с Swift 4. Срещнах този нетипичен JSON връщане, където Ints и Dates се връщат като Strings.

Погледнах Парсънг на JSON с Swift 4 на GrokSwift, Уебсайт на Apple, но не виждам нищо, което да изскача отново: променящите се типове.

Примерният код на Apple показва как да промените имената на ключовете, но ми е трудно да разбера как да променя типа на ключа.

Ето как изглежда:

{
"WaitTimes": [
{
"CheckpointIndex": "1",
"WaitTime": "1",
"Created_Datetime": "10/17/2017 6:57:29 PM"
},
{
"CheckpointIndex": "2",
"WaitTime": "6",
"Created_Datetime": "10/12/2017 12:28:47 PM"
},
{
"CheckpointIndex": "0",
"WaitTime": "8",
"Created_Datetime": "9/26/2017 5:04:42 AM"
}
]
}

Аз използвах CodingKey да преименувате ключовете на речника на съответстващ на Swift запис, както следва:

struct WaitTimeContainer: Codable {
let waitTimes: [WaitTime]

private enum CodingKeys: String, CodingKey {
case waitTimes = "WaitTimes"
}

struct WaitTime: Codable {
let checkpointIndex: String
let waitTime: String
let createdDateTime: String

private enum CodingKeys: String, CodingKey {
case checkpointIndex = "CheckpointIndex"
case waitTime = "WaitTime"
case createdDateTime = "Created_Datetime"
}
}
}

Това все още ме оставя String това трябва да бъде Int или Date, Как мога да отида за конвертиране на JSON връщане, което съдържа Int/Date/Float като String до един Int/Date/Float използване на протокола за кодиране?

Отговори:

6 за отговор № 1

Това е все още не е възможно като Swift екип е предоставил само String до датата декодер в JSONDecoder.

Винаги можете да декодирате ръчно:

struct WaitTimeContainer: Decodable {
let waitTimes: [WaitTime]

private enum CodingKeys: String, CodingKey {
case waitTimes = "WaitTimes"
}

struct WaitTime:Decodable {
let checkpointIndex: Int
let waitTime: Float
let createdDateTime: Date

init(checkpointIndex: Int, waitTime: Float, createdDateTime:Date) {
self.checkpointIndex = checkpointIndex
self.waitTime = waitTime
self.createdDateTime = createdDateTime
}

static let formatter: DateFormatter = {
let formatter = DateFormatter()
formatter.calendar = Calendar(identifier: .iso8601)
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = "MM/dd/yyyy hh:mm:ss a"
return formatter
}()

init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let checkpointIndexString = try container.decode(String.self, forKey: .checkpointIndex)
let checkpointIndex = Int(checkpointIndexString)!

let waitTimeString = try container.decode(String.self, forKey: .waitTime)
let waitTime = Float(waitTimeString)!

let createdDateTimeString =  try container.decode(String.self, forKey: .createdDateTime)

let createdDateTime = WaitTime.formatter.date(from: createdDateTimeString)!

self.init(checkpointIndex:checkpointIndex, waitTime:waitTime, createdDateTime:createdDateTime)
}

private enum CodingKeys: String, CodingKey {
case checkpointIndex = "CheckpointIndex"
case waitTime = "WaitTime"
case createdDateTime = "Created_Datetime"
}
}
}

0 за отговор № 2
public extension KeyedDecodingContainer {
public func decode(_ type: Date.Type, forKey key: Key) throws -> Date {
let dateString = try self.decode(String.self, forKey: key)
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MM/dd/yyyy hh:mm:ss a"
guard let date = dateFormatter.date(from: dateString) else {
let context = DecodingError.Context(codingPath: codingPath,
debugDescription: "Could not parse json key to a Date")
throw DecodingError.dataCorrupted(context)
}
return date
}
}

Употреба: -

let date: Date = try container.decode(Date.self, forKey: . createdDateTime)