New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Experiment: Fix(?) keypaths and add decode
overloads on NSDictionary
#109
Conversation
…ired: false, but true when created from string literal
…ust overloads to work with "isRequired" per default behaviour
Hmm, this also allows for collecting more metadata with func decode<T>(keys: String..., line: Int = #line, file: String = #file) throws -> T |
If Swift is anything like C, the variadic has to be at the end of the parameter list. although it's treated like an array, so perhaps it doesn't? Can't seem to find anything in the doc about it except you can only have 1 variadic in a parameter list. |
Ok, quick playground test shows it's ok as long as the types are all the same, the compiler is ok. Not sure, but as this is a template, err ... generic, we aren't expecting this to be overridden in subclasses, yes? Otherwise I am not sure subclassing isn't going to be ... weird, with the default parameters... |
Overriding it actually turned out to be impossible (currently), but you're right, it should be final. |
Also, got this to work! (for separate pull request probably though) public enum OptionalKey { // Better name needed?
case optional(String)
case required(String)
case canBeMissing(String)
}
let dict = NSDictionary()
let a: Int? = try! dict.decode("required", .required("alsoRequired"), .optional("yay"), .canBeMissing("more yay")) |
The The cases Perhaps a name like I haven't been keeping up with this, so I am unsure about the meaning of the cases exactly, but perhaps it should be The problem with that is that this naming confuses the meaning of optional. =( What is the difference between the optional case and the canBeMissing case? |
@voidref I'm so unsure about everything, but to just answer your questions: The reason for the // Does not compile:
let a: Int = json.decode(.required("a")) // "a" becomes OptionalKey
// Compiles but never returns nil:
let a: Int? = json.decode(.required("a")) // "a" becomes OptionalKey
// Compiles and works as expected:
let a: Int = json.decode("a") // "a" becomes String/KeyPath |
Given this answer, consider Gah, naming, it's hard. I am not totally happy with those. Perhaps it's because the underlying logic is too subtle. Would it be reasonable to wrap both the missing and the nsnull case into just one 'optional'? |
Closing this now even though some aspects of this have potential and could be revisited. If we're doing this it should be more like #97, which perhaps isn't that bad if you don't try to over-abuse the DecodingContext parameters. |
Adds overloads of the following form:
Which enables the following usage:
With the side effects of making the
OptionalKeyPath
/KeyPath
slightly more complex and with changes to default behaviours:I thought about adding a
.optional
property onString
instead ofOptionalKey("key")
, but thought it was too vague.This would fix #26, while maintaining the following features:
I'm not at all sold on this yet however. Some rambling thoughts:
AnyObject
s this adds verbosity=>
works like a subscript, and the added ? in=>?
works like in optional chaining. Though perhaps this is for the best because the implementation is made simpler, fixes one edge cases where the first key(s) are required where the latter are optional, and because this is how Decodable actually works.Also in the future
OptionalKey
could add functionality to distinguish between acceptingNSNull
and accepting missing keys, a small but useful feature.TODO: