0

Suppose we have the following structure:

struct TestCod: Codable {
    var txt = ""
    var date = Date()
}

If we are expecting JSON in two similar formats, how could we handle decoding?

JSON A:

{
"txt":"stack",
"date":589331953.61679399
}

JSON B:

{
"txt":"overflow",
"date":"2019-09-05"
}
rmaddy
  • 314,917
  • 42
  • 532
  • 579
GoldenJoe
  • 7,874
  • 7
  • 53
  • 92

1 Answers1

2

As shown in the possible duplicate post I have already mentioned in comments, you need to create a custom date decoding strategy:

First create your date formatter for parsing the date string (note that this assumes your date is local time, if you need UTC time or server time you need to set the formatter timezone property accordingly):

extension Formatter {
    static let yyyyMMdd: DateFormatter = {
        let formatter = DateFormatter()
        formatter.calendar = Calendar(identifier: .iso8601)
        formatter.locale = Locale(identifier: "en_US_POSIX")
        formatter.dateFormat = "yyyy-MM-dd"
        return formatter
    }()
}

Then create a custom decoding strategy to try all possible date decoding strategy you might need:

extension JSONDecoder.DateDecodingStrategy {
    static let deferredORyyyyMMdd  = custom {
        let container = try $0.singleValueContainer()
        do {
            return try Date(timeIntervalSinceReferenceDate: container.decode(Double.self))
        } catch {
            let string = try container.decode(String.self)
            if let date = Formatter.yyyyMMdd.date(from: string)  {
                return date
            }
            throw DecodingError.dataCorruptedError(in: container, debugDescription: "Invalid date: \(string)")
        }
    }
}

Playground testing:

struct TestCod: Codable {
    let txt: String
    let date: Date
}

let jsonA = """
{
"txt":"stack",
"date":589331953.61679399
}
"""
let jsonB = """
{
"txt":"overflow",
"date":"2019-09-05"
}
"""

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .deferredORyyyyMMdd
let decodedJSONA = try! decoder.decode(TestCod.self, from: Data(jsonA.utf8))
decodedJSONA.date  //  "Sep 4, 2019 at 8:19 PM"
let decodedJSONB = try! decoder.decode(TestCod.self, from: Data(jsonB.utf8))
decodedJSONB.date  //  "Sep 5, 2019 at 12:00 AM"
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571