Comments (11)
Sample app is attached, please don't return non-optional
Date
from thedecode(from:)
method as a workaround solution to the problem, because I need to store nilDate?
in the model for some cases.
As I mentioned, for storing Date?
you need to return Date
in decode(from:)
and return Date?
in decodeIfPresent(from:)
. Your DateCoder
implementation should look like this:
struct DateCoder: HelperCoder {
func decode(from decoder: Decoder) throws -> Date {
// return Date, this implementation will be used when you are storing Non-optional Date in Model
}
func decodeIfPresent(from decoder: Decoder) throws -> Date? {
// return optional Date, this implementation will be used when you are storing optional Date in Model
}
}
Please try to follow this guideline and try to write some test cases for your use cases, please let me know if any test case fails with your implementation code attached.
from metacodable.
I have the following
@Codable
model and itsHelperCoder
struct:@Codable struct TestModel { @CodedBy(DateCoder()) var startDate: Date? } struct DateCoder: HelperCoder { func decode(from decoder: Decoder) throws -> Date? { var container = try decoder.unkeyedContainer() let dateStr = try container.decode(String.self) let df = ISO8601DateFormatter() let date = df.date(from: dateStr) return date } }
Can you try with returning Date
type instead of Date?
in DateCoder
implementation? That should fix your issue:
struct DateCoder: HelperCoder {
func decode(from decoder: Decoder) throws -> Date {
var container = try decoder.unkeyedContainer()
let dateStr = try container.decode(String.self)
let df = ISO8601DateFormatter()
let date = df.date(from: dateStr)
return date
}
}
from metacodable.
That solves the syntax error but doesn't solve the problem, there should be a way to decode optional Dates by returning optional Date from the HelperCoder
.
There are lots of use cases where we need something like: var someDate: Date?
in the models .
If I implement decodeIfPresent(from: )
instead of decode(from:)
in the HelperCoder
, the compiler auto completes the function signature with the return type of Date??
which should be Date?
.
I also tried to use @Default(nil)
for the optional date in the model but it also gives an error: Generic parameter 'T' could not be inferred
.
from metacodable.
That solves the syntax error but doesn't solve the problem, there should be a way to decode optional Dates by returning optional Date from the
HelperCoder
.
This use-case can be handled with current implementation as well, HelperCoder
has optional requirement decodeIfPresent(from:)
, which you can implement in your DateCoder
, to indicate what happens when you want to decode optional Date
.
The default implementation of decodeIfPresent(from:)
just returns result from decode(from:)
and returns nil
if this method throws error.
from metacodable.
That solves the syntax error but doesn't solve the problem, there should be a way to decode optional Dates by returning optional Date from the
HelperCoder
.This use-case can be handled with current implementation as well,
HelperCoder
has optional requirementdecodeIfPresent(from:)
, which you can implement in yourDateCoder
, to indicate what happens when you want to decode optionalDate
.The default implementation of
decodeIfPresent(from:)
just returns result fromdecode(from:)
and returnsnil
if this method throws error.
kindly look at the edited comment above regarding decodeIfPresent(from:)
which produces the same problem as well.
from metacodable.
If I implement
decodeIfPresent(from: )
instead ofdecode(from:)
in theHelperCoder
, the compiler auto completes the function signature with the return type ofDate??
which should beDate?
.
Can you share the implementation snippet you are trying? I will be able to suggest changes that will make your use-case work.
from metacodable.
Sample app is attached, please don't return non-optional Date
from the decode(from:)
method as a workaround solution to the problem, because I need to store nil Date?
in the model for some cases.
TestCodableMacro.zip
from metacodable.
Thank you @soumyamahunt for the last pattern you provided which really solves the issue, but the only take away in this pattern is that I must provide the implementation of decode(from:)
to avoid the compiler error: Type 'DateCoder' does not conform to protocol 'HelperCoder'
, so I just implemented it like this to return a dummy date:
func decode(from decoder: Decoder) -> Date {
Date()
}
if you could fix this to only require func decodeIfPresent(from:)
when the model value is optional that would be cool
from metacodable.
if you could fix this to only require
func decodeIfPresent(from:)
when the model value is optional that would be cool
The use of HelperCodable
is to provide custom decoder/encoder that will decode/encode a type and it's optional variant. This is the same in principle with the standard library where decode
is used to decode a basic type (i.e. Int
) decodeIfPresent
to decode optional of that type.
You should implement decode(from:)
to decode the actual Date
type and reuse that implementation in decodeIfPresent(from:)
and provide custom logic to handle failure (i.e. returning nil
).
Anyway, closing this since there is no issue here.
from metacodable.
Posting this comment after closing the issue ..
Sorry but that sounds unreasonable to provide implementations for both the basic type and its optional variant for the case when the value in question may or may not return, providing only: decodeIfPresent
implementation is enough, like we already do with the init(from decoder:)
.
Moreover, the implementation of the basic type and its optional variant will not be the same, so it can't be reused in both.
I'm stuck in a similar case, to do a very basic data conversion (string to int), providing a whole struct with double implementations produces too much boilerplate code. (i've emailed. you about it by the way).
from metacodable.
I had the same issue as @murad1981 and managed to fix it.
While the last messages here went a bit off the rail, the fix is really easy:
@Codable
struct Demo {
@CodedBy(CustomDateCoder(format: "yyyy-MM-dd"))
var myDate: Date
@CodedBy(CustomDateCoder(format: "HH:mm"))
var myTime: Date?
}
fileprivate struct CustomDateCoder: HelperCoder {
var format: String
func decode(from decoder: any Decoder) throws -> Date {
let container = try decoder.singleValueContainer()
let dateString = try container.decode(String.self)
if dateString.isEmpty {
throw DecodingError.valueNotFound(Date.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Date string is empty"))
}
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = format
guard let date = dateFormatter.date(from: dateString) else {
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Cannot format date"))
}
return date
}
}
from metacodable.
Related Issues (20)
- Note of appreciation :) + Some questions HOT 6
- Assistance with rojopolis/spellcheck-github-actions ? HOT 4
- Derive access level of generate CodingKeys from @Codable model HOT 5
- Provide default value of nil for empty strings HOT 5
- Does IgnoreCoding support properties with didSet? HOT 1
- Distribute a prebuilt binary HOT 3
- SwiftData class: Method does not override any method from its superclass HOT 14
- @CodedBy and ValueCoder not in scope HOT 1
- Support for different coding keys for encoding / decoding the same property
- Cocoapods installation does not work HOT 8
- `@CodedAs` fails with same keys in different casing
- A way to log when a property defaults on the default value HOT 3
- [Bug] `CodedAs` causes crash in enum when encoding. HOT 5
- `MetaProtocolCodable` cannot handle Optional value correctly HOT 2
- [Feature Request] Encodable Default Value Handling HOT 2
- Xcode build archive fails HOT 2
- [Feature Request] No HelperCoder generated when check compilation condition HOT 3
- No value associated with key CodingKeys HOT 3
- Custom parsing logic inside decoding method HOT 1
- [Help wanted] How can it test the macro test? HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from metacodable.