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

Youming Lin ylin at us.ibm.com
Wed Aug 30 13:17:54 CDT 2017

One downside I see is that the encoder wouldn't know if this specific field
was originally a number instead of a string. If the same Codable struct is
used for GET and POST, for example, the post-encode JSON string could be
invalid because the server expects a number instead of a string for that

An explicit mapping of JSON value type to Codable ivar type would be
needed, but this can create validation issues because while all numbers can
be converted to strings (decode is OK), not all strings can be converted to
numbers (encode is not OK).


Youming Lin
IBM Cloud, Swift at IBM, Kitura developer
Austin, TX
GitHub: @youming-lin

From:	"Sneed, Brandon via swift-corelibs-dev"
            <swift-corelibs-dev at swift.org>
To:	"swift-corelibs-dev at swift.org" <swift-corelibs-dev at swift.org>
Date:	08/30/2017 01:00 PM
Subject:	[swift-corelibs-dev] Adding type conversion capabilities to
            JSON	encode/decode
Sent by:	swift-corelibs-dev-bounces at swift.org

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

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-corelibs-dev/attachments/20170830/b4f5041b/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: graycol.gif
Type: image/gif
Size: 105 bytes
Desc: not available
URL: <https://lists.swift.org/pipermail/swift-corelibs-dev/attachments/20170830/b4f5041b/attachment.gif>

More information about the swift-corelibs-dev mailing list