вместо разнородного словаря или коллекции массивов), то вы можете использовать подход Хэмиша.
аюсь сериализовать структуру в строку с помощью Encodable + JSONEncoder Swift 4. Объект может содержать разнородные значения, такие как String, Array, Date, Int и т. Д.
Используемый подход прекрасно работает, за исключением даты. JSONEncoder-хdateEncodingStrategy
собственность не оказывает никакого влияния.
Вот фрагмент, который воспроизводит поведение в Playground:
struct EncodableValue:Encodable {
var value: Encodable
init(_ value: Encodable) {
self.value = value
}
func encode(to encoder: Encoder) throws {
try value.encode(to: encoder)
}
}
struct Bar: Encodable, CustomStringConvertible {
let key: String?
let value: EncodableValue?
var description: String {
let encoder = JSONEncoder()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "E, d MMM yyyy"
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
encoder.dateEncodingStrategy = .formatted(dateFormatter)
let jsonData = try? encoder.encode(self)
return String(data: jsonData!, encoding: .utf8)!
}
}
let bar1 = Bar(key: "bar1", value: EncodableValue("12345"))
let bar2 = Bar(key: "bar2", value: EncodableValue(12345))
let bar3 = Bar(key: "bar3", value: EncodableValue(Date()))
print(String(describing: bar1))
print(String(describing: bar2))
print(String(describing: bar3))
Выход:
"{"key":"bar1","value":"12345"}\n"
"{"key":"bar2","value":12345}\n"
"{"key":"bar3","value":539682026.06086397}\n"
Для объекта bar3: я ожидаю что-то вроде"{"key":"bar3","value":"Thurs, 3 Jan 1991"}\n"
, но возвращает дату в формате стратегии по умолчанию .deferToDate.
## РЕДАКТИРОВАТЬ 1 ##
Итак, я запустил тот же код в XCode 9, и он выдает ожидаемый результат, то есть правильно форматирует дату в строку. Я думаю, что 9.2 имеет небольшое обновление до Swift 4, что нарушает эту функцию. Не уверенны что делать дальше.
## РЕДАКТИРОВАТЬ 2 ##
В качестве временного средства я использовал следующий фрагмент, прежде чем перейти к подходу @ Hamish с использованием замыкания.
struct EncodableValue:Encodable {
var value: Encodable
init(_ value: Encodable) {
self.value = value
}
func encode(to encoder: Encoder) throws {
if let date = value as? Date {
var container = encoder.singleValueContainer()
try container.encode(date)
}
else {
try value.encode(to: encoder)
}
}
}