Hi Brandon,
Thanks for looking at this! We’ve got plans internally to potentially
add a strategy to `JSONEncoder`/`JSONDecoder` to allow lenient
conversions like this — i.e. implicitly stringify numbers (or parse
them from string input), among some others.
This would be opt-in for consumers of `JSONDecoder` while not requiring
any special annotations on `Codable` types.
— Itai
On 30 Aug 2017, at 10:59, Sneed, Brandon via swift-corelibs-dev wrote:
Hi everyone,
Just throwing this out to see if anyone else is working on this, or
has opinions/suggestions on how it’s implemented. I’d like to add
this to the Codable/JSONDecoder/JSONEncoder system if no one else is
working on it.
Type type conversion, I mean given this JSON payload:
{
"name": "Endeavor”,
"abv": 8.9,
"brewery": "Saint Arnold”,
"style": "ipa"
}
and a struct defined as:
struct Beer: Codable {
let name: String
let abv: String
let brewery: String
let style: BeerStyle
}
Notice that “abv” is a number in the JSON, but a String in the
struct. I’d like to make it such that I can let the system know
it’s ok to convert it from a number to a string as opposed to
throwing an exception. The benefits are:
1. It’s defensive; service types can change without causing my
application to crash.
2. It allows a developer to work with the types they want to
work with as opposed to what the server provides, thus saving them
time of writing a custom encode/decode code for all members.
The argument against it that I’ve heard is generally “it’s a
service bug, make them fix it”, which is valid but the reality is
we’re not all in control of the services we injest. The same type
of logic could be applied to a member name changing, though I
haven’t seen this happen often in practice. I do see types in a
json payload change with some frequency though. I think much of the
reason stems from the fact that type conversion in javascript is
effectively free, ie: you ask for a String, you get a String if
possible.
To implement this type conversion in practice, looking at it from the
point of view using Codable/JSON(en/de)coder, one way would be to make
it opt-in:
struct Beer: Codable, CodingConvertible {
let name: String
let abv: String
let brewery: String
let style: BeerStyle
}
I like this because looking at the struct, the members still remain
clear and relatively unambiguous. The downside is it’s unknown
which member is likely to get converted. And since it’s opt-in,
conversion doesn’t happen if the CodingConvertible conformance
isn’t adhered to.
Another option would be to box each type, like so:
struct Beer: Codable {
let name: String
let abv: Convertible<String>
let brewery: String
let style: BeerStyle
}
This seems tedious for developers, but would show which types are
being converted. It does however seriously weaken benefit #1 above.
Those example usages above aside, I do think it’d be best if this
conversion behavior was the default and no end-developer changes
required. I think that could be done without impact to code that’s
been already been written against the JSON en/decode bits.
I’m very open to alternatives, other ideas, or anything else you
might have to say on the subject. Thanks for reading!
Brandon Sneed
_______________________________________________
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev
_______________________________________________
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev