[swift-corelibs-dev] Adding type conversion capabilities to JSON encode/decode

Itai Ferber iferber at apple.com
Wed Aug 30 13:22:34 CDT 2017


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 at swift.org
> https://lists.swift.org/mailman/listinfo/swift-corelibs-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-corelibs-dev/attachments/20170830/46fa8415/attachment.html>


More information about the swift-corelibs-dev mailing list