вместо разнородного словаря или коллекции массивов), то вы можете использовать подход Хэмиша.

аюсь сериализовать структуру в строку с помощью 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)
        }

    }
}

Ответы на вопрос(1)

Ваш ответ на вопрос