marksands/BetterCodable

Decoding Date?

npb12 opened this issue ยท 4 comments

npb12 commented

I have a field updatedON that comes as a nil value from the api, but gets updated in the local DB after an object is updated. Not sure how to handle this. Essentially I'd like to combine ISO8601Strategy and DefaultCodableStrategy

any update?

It sounds like you might want something like a @OptionalDateValue?

It's not too much code to implement yourself, but if there's interest I could be persuaded to add it to the library.

no no, i dont want optional.
for example if i have a model:

struct MyModel: Codable {
    var departureDate: Date
    var returnDate: Date
}

and server send to me a json like this:
{ "departureDate": "2022-10-10T09:09:09", "returnDate": "2022-11-10T09:09:09" }

// MyModel().departureDate: 2022-10-10 09:09:09 +0000
// MyModel().returnDate: 2022-11-10 09:09:09 +0000

everything is ok

but if server send same json without returnDate , i want set it to my model Today date

{ "departureDate": "2022-10-10T09:09:09", "returnDate": null }
{ "departureDate": "2022-10-10T09:09:09", "returnDate": 3456765 }
{ "departureDate": "2022-10-10T09:09:09"}

// MyModel().departureDate: 2022-10-10 09:09:09 +0000
// MyModel().returnDate: Date() function

@SajjadKharrazi ๐Ÿ‘ Then I suppose my advice only applies to @npb12 ๐Ÿ˜„

In your case, you can use a nested property wrapper to accomplish what you want. It's a little clunky, but it works ๐ŸŽ‰!

  enum DefaultToNowTimeStampDateValue: DefaultCodableStrategy {
    static var defaultValue: DateValue<TimestampStrategy> {
      .init(wrappedValue: Date())
    }
  }
    
  struct MyModel: Codable {
    @DefaultCodable<DefaultToNowTimeStampDateValue>
    @DateValue<TimestampStrategy>
    var returnDate: Date
  }
    
  let jsonData1 = #"{ "returnDate": null }"#.data(using: .utf8)!
  let fixture1 = try JSONDecoder().decode(MyModel.self, from: jsonData1)
  XCTAssertEqual(fixture1.returnDate, Date()) // null, Defaults to "Date()"

  let jsonData2 = #"{ }"#.data(using: .utf8)!
  let fixture2 = try JSONDecoder().decode(MyModel.self, from: jsonData2)
  XCTAssertEqual(fixture2.returnDate, Date()) // missing, Defaults to "Date()"

  let jsonData3 = #"{ "returnDate": 0 }"#.data(using: .utf8)!
  let fixture3 = try JSONDecoder().decode(MyModel.self, from: jsonData3)
  XCTAssertEqual(fixture3.returnDate, Date()) // expected, defaults to 1970...

Note that the DateValueCodableStrategy must be the same in your DefaultCodableStrategy as well as your MyModel's variable type. The DefaultCodableStrategy must wrap the DateValue's strategy in the type, since the @DefaultCodable's wrappedValue is of type DateValue<DateValueCodableStrategy>, and not Date.