-2

I am using Codable protocol and JSONDecoder for decoding JSON that I get from my webservice. And it works really nice. One thing, though, is that I sometimes get Date in different formats, so I want to set custom decoding for this field.

Browsing through SO and net, I found this can be done, but I also have to decode all other fields manually. Since I have many fields, I would like to decode all of them automatically and then just this one field to decode manually.

Is this possible?

EDIT:

I will provide some more info, as it seems this question is making a lot of confusion.

I have JSON that has many fields. My struct Person adopts Codable. I use JSONDecoder like this

let person = try self.jsonDecoder.decode(Person.self, from: data)

Now all fields are set automatically to struct. But sometimes I have one or more fields where I would like to manually decode them. In this case it is just date, which can be in various formats. I would like to use if possible this same line:

let person = try self.jsonDecoder.decode(Person.self, from: data)

where all other fields would be decoded automatically, and just Date would have manual encoding.

MegaManX
  • 8,766
  • 12
  • 51
  • 83
  • What happens when you try it? – Desdenova Jan 09 '19 at 14:34
  • Your question is already answer here https://stackoverflow.com/questions/46458487/how-to-convert-a-date-string-with-optional-fractional-seconds-using-codable-in-s. You can provide your own dateDecodingStrategy to your decoder. – Leo Dabus Jan 09 '19 at 16:52

1 Answers1

0

You can simply set the dateDecodingStrategy of the JSONDecoder you use for decoding to formatted and supply a DateFormatter with the specified format, then if it fails, supply the other date format. See a full working code with examples:

struct VaryingDate: Decodable {
    let a:String
    let date:Date
}

let jsonWithFirstDate = "{\"a\":\"first\",\"date\":\"2019/01/09\"}".data(using: .utf8)!
let jsonWithSecondDate = "{\"a\":\"first\",\"date\":\"2019-01-09T12:12:12\"}".data(using: .utf8)!

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy/MM/dd"
let jsonDecoder = JSONDecoder()
jsonDecoder.dateDecodingStrategy = .formatted(dateFormatter)
do {
    try jsonDecoder.decode(VaryingDate.self, from: jsonWithFirstDate) // succeeds
    try jsonDecoder.decode(VaryingDate.self, from: jsonWithSecondDate) // fails, as expected
} catch {
    dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
    try jsonDecoder.decode(VaryingDate.self, from: jsonWithSecondDate) // succeeds with the updated date format
}
Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116
  • I don't think that what's the OP meant – Mohmmad S Jan 09 '19 at 14:43
  • @7bebMrto that is what I understood from the question, so let OP answer if this is what he actually meant or not :) – Dávid Pásztor Jan 09 '19 at 14:44
  • he clearly said he has too much fields to decode and if he overrode the decoder he would have to decode all of it manually, and he is asking if he can decode 1 field manually and then let the rest automatically without having to manually do them. – Mohmmad S Jan 09 '19 at 14:46
  • @7bebMrto the whole point is that you don't need to decode any fields manually. `dateDecodingStrategy` handles that for you automatically... – Dávid Pásztor Jan 09 '19 at 14:46
  • @LeoDabus thanks for spotting that, updated my answer – Dávid Pásztor Jan 09 '19 at 14:49