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

Youming Lin ylin at us.ibm.com
Wed Aug 30 15:18:13 CDT 2017


Brandon

>JSON’s types effectively end up matching specifically to primitives, of
which there is no mechanism to override the behavior of how a String gets
decoded for instance.

You can override the default behavior with your own custom init(from:)
implementation for your Codable struct:
https://developer.apple.com/documentation/swift/decodable/2894081-init

You can check Foundation source code (i.e., the URL struct) on how this can
be implemented.

Thanks,

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:	Tony Parker <anthony.parker at apple.com>
Cc:	"swift-corelibs-dev at swift.org" <swift-corelibs-dev at swift.org>
Date:	08/30/2017 03:07 PM
Subject:	Re: [swift-corelibs-dev] Adding type conversion capabilities to
            JSON encode/decode
Sent by:	swift-corelibs-dev-bounces at swift.org



Hi Tony,

I like the idea that the type itself is responsible for the conversion.  My
own json encode/decode library worked this way and it was really great,
however in trying to leverage Swift4 into it, or to replace it, I just
don’t see how that’s possible given how it’s currently structured.

JSON’s types effectively end up matching specifically to primitives, of
which there is no mechanism to override the behavior of how a String gets
decoded for instance.  The only way I can think of to accomplish that is to
create *another* type, JSONString for example, but since String is a
struct, I can’t subclass it, and instead need to have the real value buried
inside of it … it seems to start getting messy very quickly.  It also adds
the obfuscation of dealing with yet another type, which I’m not against,
but just feels less than ideal.


Brandon Sneed

From: <anthony.parker at apple.com> on behalf of Tony Parker
<anthony.parker at apple.com>
Date: Wednesday, August 30, 2017 at 11:30 AM
To: "Sneed, Brandon" <brsneed at ebay.com>
Cc: Itai Ferber <iferber at apple.com>, "swift-corelibs-dev at swift.org"
<swift-corelibs-dev at swift.org>
Subject: Re: [swift-corelibs-dev] Adding type conversion capabilities to
JSON encode/decode

I’m still not convinced that we should actually provide such a strategy.

Conversions like those below seem like the domain of each type that is
being decoded. If, in a particular type, the “number” can be either a true
number or a string, then that type can try decoding it as one or the other
and fall back as required. That puts the responsibility of doing that kind
of conversion in the type itself.

JSON has very few types already. I’m not sure we want to blur the line
between numbers and strings automatically…

- Tony


      On Aug 30, 2017, at 11:24 AM, Sneed, Brandon via swift-corelibs-dev <
      swift-corelibs-dev at swift.org> wrote:

      Hi Itai,

      No problem!  Thanks for the heads up.  Is there any way I could be
      involved?  Happy to do the work to whatever guidance your team might
      have.  I’m mostly just interested in it being there soon, hence
      volunteering.

      Thanks!


      Brandon Sneed

      From: <iferber at apple.com> on behalf of Itai Ferber <iferber at apple.com
      >
      Date: Wednesday, August 30, 2017 at 11:22 AM
      To: "Sneed, Brandon" <brsneed at ebay.com>
      Cc: "swift-corelibs-dev at swift.org" <swift-corelibs-dev at swift.org>
      Subject: Re: [swift-corelibs-dev] Adding type conversion capabilities
      to JSON encode/decode

      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
      _______________________________________________
      swift-corelibs-dev mailing list
      swift-corelibs-dev at swift.org
      https://lists.swift.org/mailman/listinfo/swift-corelibs-dev
 _______________________________________________
swift-corelibs-dev mailing list
swift-corelibs-dev at swift.org
https://urldefense.proofpoint.com/v2/url?u=https-3A__lists.swift.org_mailman_listinfo_swift-2Dcorelibs-2Ddev&d=DwIGaQ&c=jf_iaSHvJObTbx-siA1ZOg&r=gkRZBtsmKeGPCOlAIRJoOA&m=ViDSVPImta3StTVAcktby2PMF_-du5itzz47jo-tNHg&s=zRuNQ3NLxpfhFBewRTkoMWZnpvHlm6Ja-ot9_pwAgqI&e=



-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-corelibs-dev/attachments/20170830/508c0e8e/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/508c0e8e/attachment.gif>


More information about the swift-corelibs-dev mailing list