Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error Decoding Date with Swift

Tags:

json

ios

swift

For example my JSON looks like so:

{ 
   createdAt = "2018-06-13T12:38:22.987Z"  
}

My Struct looks like so:

struct myStruct {
    let createdAt: Date
}

Decode like so:

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601

When I am decoding I get this error:

failed to decode, dataCorrupted(Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "results", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "createdAt", intValue: nil)], debugDescription: "Expected date string to be ISO8601-formatted.", underlyingError: nil))

I understand it says that the string was expected to be ISO8601 formatted, but isn't it?

like image 398
farhan Avatar asked Jul 14 '26 19:07

farhan


2 Answers

The standard ISO8601 date format doesn't include fractional seconds so you need to use a custom date formatter for the date decoding strategy.

let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(dateFormatter)
like image 162
rmaddy Avatar answered Jul 17 '26 14:07

rmaddy


For those encountering this with the new OpenApiGenerator in Swift, here's how you go:

  1. Add this class to your project:

     struct CustomDateTranscoder: DateTranscoder {
     public func encode(_ date: Date) throws -> String { ISO8601DateFormatter().string(from: date) }
    
     public func decode(_ dateString: String) throws -> Date {
         let formatter = ISO8601DateFormatter()
         formatter.formatOptions = [.withFractionalSeconds]
         guard let date = formatter.date(from: dateString) else {
             throw DecodingError.dataCorrupted(
                 .init(codingPath: [], debugDescription: "Expected date string to be ISO8601-formatted.")
             )
         }
         return date
     }
    

    }

And then when creating your client, add this transcoder to the configuration:

client = Client(
    serverURL: try! Servers.server1(),
    configuration: .init(dateTranscoder: CustomDateTranscoder()),
    transport: URLSessionTransport()
)
like image 31
Vahid Avatar answered Jul 17 '26 13:07

Vahid



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!