> On Aug 30, 2017, at 3:12 PM, Sneed, Brandon <brsn...@ebay.com> wrote:
> 
> Thanks Tony,
>  
> Ah.  That should work, and covers benefit #2 I mentioned very nicely.  Only 
> downside is that as a developer on an app I may not expect that type to 
> change on the server side so I wouldn’t do it by default, and when it does 
> happen, I then need to apply it to each of its siblings because if it can 
> happen to one, it can happen to the others.

In this case, the server decides to send a String instead of a numeric value 
for many kinds of types?

I understand that some JSON libraries have options to stringify all numeric 
values in an attempt to preserve ‘exactness’, although I would argue that this 
depends on what you do with the numeric value on the other side…

- Tony

>  
> Javascript and GSON handle this in a relatively safe way.  I think us having 
> a way to opt-in to the same capabilities is good.  When I say opt-in, I mean 
> at the containing-struct level, not necessarily per member, nor do I want to 
> do a custom init every time.  I’m sure there’s a happy place in the middle, 
> just not sure what it is. 
>  
> I do also want to add that I very much appreciate the discussion.  We’re 
> having one internally too, and the divide seems to be about the same as 
> what’s on the mailing list (which seems about 50/50).
>  
>  
> Brandon Sneed
>  
> From: <anthony.par...@apple.com> on behalf of Tony Parker 
> <anthony.par...@apple.com>
> Date: Wednesday, August 30, 2017 at 3:04 PM
> To: "Sneed, Brandon" <brsn...@ebay.com>
> Cc: Youming Lin <y...@us.ibm.com>, "swift-corelibs-dev@swift.org" 
> <swift-corelibs-dev@swift.org>
> Subject: Re: [swift-corelibs-dev] Adding type conversion capabilities to JSON 
> encode/decode
>  
> I haven’t tried this myself yet, but you could imagine creating a type which 
> represents an ABV and decodes using a single value container. Then, your 
> custom behavior goes into the Codable implementation of this ABV type.
>  
> Struct Beer then looks like:
>  
> struct Beer: Codable {
>     let name: String
>     let abv: ABV
>     …
> }
>  
> ABV can have API on it to get the numeric value or String value; or that 
> could go into Beer and it would abstract the ABV type from callers.
>  
> - Tony
> 
> 
> On Aug 30, 2017, at 2:42 PM, Sneed, Brandon <brsn...@ebay.com 
> <mailto:brsn...@ebay.com>> wrote:
>  
> Thanks Youming,
>  
> That’s not quite what I meant.  I may have misinterpreted what Tony was 
> saying though.
>  
> I wanted to do conversion on String, not the containing type.  The problem of 
> doing it on the containing type is that as soon as you need one field to be 
> custom, you’re roped into handling all the others.  For a small struct, not a 
> big deal, for larger ones, it is.  Something like this is what I tried:
>  
> import Cocoa
>  
> let jsonString = "{" +
>     "\"name\": \"Endeavor\"," +
>     "\"abv\": 8.9," +
>     "\"brewery\": \"Saint Arnold\"," +
>     "\"style\": \"ipa\"}"
>  
> struct Beer: Codable {
>     let name: String
>     let abv: String
>     let brewery: String
>     let style: String
> }
>  
> extension String {
>     init(from decoder: Decoder) throws {
>         print("i got hit.")
>         let value = try decoder.singleValueContainer().decode(String.self)
>         self.init(value)
>     }
> }
>  
> let jsonData = jsonString.data(using: .utf8)
> let decoder = JSONDecoder()
> let beer = try! decoder.decode(Beer.self, from: jsonData!)
>  
> fatal error: 'try!' expression unexpectedly raised an error: 
> Swift.DecodingError.typeMismatch(Swift.String, 
> Swift.DecodingError.Context(codingPath: [__lldb_expr_17.Beer.(CodingKeys in 
> _C8902E33F84CE6946081129DAF1824E1).abv], debugDescription: "Expected to 
> decode String but found a number instead.", underlyingError: nil)): file 
> /Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-900.0.59/src/swift/stdlib/public/core/ErrorType.swift,
>  line 181
>  
>  
>  
> From: Youming Lin <y...@us.ibm.com <mailto:y...@us.ibm.com>>
> Date: Wednesday, August 30, 2017 at 2:35 PM
> To: "Sneed, Brandon" <brsn...@ebay.com <mailto:brsn...@ebay.com>>
> Cc: Tony Parker <anthony.par...@apple.com <mailto:anthony.par...@apple.com>>, 
> "swift-corelibs-dev@swift.org <mailto:swift-corelibs-dev@swift.org>" 
> <swift-corelibs-dev@swift.org <mailto:swift-corelibs-dev@swift.org>>, 
> "swift-corelibs-dev-boun...@swift.org 
> <mailto:swift-corelibs-dev-boun...@swift.org>" 
> <swift-corelibs-dev-boun...@swift.org 
> <mailto:swift-corelibs-dev-boun...@swift.org>>
> Subject: Re: [swift-corelibs-dev] Adding type conversion capabilities to JSON 
> encode/decode
>  
> Brandon
> 
> I cooked up a simple example and it works as expected.
> 
> ylin@youming-mbpr:~/Swift/Configuration$ swift
> Welcome to Apple Swift version 4.0-dev (LLVM 2dedb62a0b, Clang b9d76a314c, 
> Swift 0899bd328a). Type :help for assistance.
> 1> import Foundation
> 2> struct A: Codable { 
> 3. var integer: Int 
> 4. 
> 5. public init(integer: Int) { 
> 6. self.integer = integer 
> 7. } 
> 8. 
> 9. public init(from decoder: Decoder) throws { 
> 10. print("Custom decoder") 
> 11. let container = try decoder.container(keyedBy: CodingKeys.self) 
> 12. integer = try container.decode(Int.self, forKey: .integer) 
> 13. } 
> 14. } 
> 15. 
> 16. try! JSONDecoder().decode(A.self, from: JSONEncoder().encode(A(integer: 
> 42)))
> Custom decoder
> $R0: A = {
> integer = 42
> }
> 
> You should be able to implement your custom init to convert the number into a 
> string and JSONDecoder should use that automatically.
> 
> Thanks,
> 
> Youming Lin
> IBM Cloud, Swift@IBM, Kitura developer
> Austin, TX
> GitHub: @youming-lin
> 
> <image001.gif>"Sneed, Brandon" ---08/30/2017 04:14:57 PM---Thanks Youming, 
> Ok, thanks! I did try that, but I can’t seem to figure out how to make it 
> actually
> 
> From: "Sneed, Brandon" <brsn...@ebay.com <mailto:brsn...@ebay.com>>
> To: Youming Lin <y...@us.ibm.com <mailto:y...@us.ibm.com>>
> Cc: Tony Parker <anthony.par...@apple.com <mailto:anthony.par...@apple.com>>, 
> "swift-corelibs-dev@swift.org <mailto:swift-corelibs-dev@swift.org>" 
> <swift-corelibs-dev@swift.org <mailto:swift-corelibs-dev@swift.org>>, 
> "swift-corelibs-dev-boun...@swift.org 
> <mailto:swift-corelibs-dev-boun...@swift.org>" 
> <swift-corelibs-dev-boun...@swift.org 
> <mailto:swift-corelibs-dev-boun...@swift.org>>
> Date: 08/30/2017 04:14 PM
> Subject: Re: [swift-corelibs-dev] Adding type conversion capabilities to JSON 
> encode/decode
> 
> 
> 
> Thanks Youming,
> 
> Ok, thanks! I did try that, but I can’t seem to figure out how to make it 
> actually get used in the decoding process. That being my preferred way, I 
> tried it first. I chalked it not working up to Swift not knowing which of the 
> 2 init(from decoder:) functions to call, mine or theirs. But, maybe there’s 
> something I’m missing here.
> 
> Any insight is appreciated.
> 
> Thanks!
> 
> 
> 
> Brandon Sneed
> 
> From: Youming Lin <y...@us.ibm.com <mailto:y...@us.ibm.com>>
> Date: Wednesday, August 30, 2017 at 1:18 PM
> To: "Sneed, Brandon" <brsn...@ebay.com <mailto:brsn...@ebay.com>>
> Cc: Tony Parker <anthony.par...@apple.com <mailto:anthony.par...@apple.com>>, 
> "swift-corelibs-dev@swift.org <mailto:swift-corelibs-dev@swift.org>" 
> <swift-corelibs-dev@swift.org <mailto:swift-corelibs-dev@swift.org>>, 
> "swift-corelibs-dev-boun...@swift.org 
> <mailto:swift-corelibs-dev-boun...@swift.org>" 
> <swift-corelibs-dev-boun...@swift.org 
> <mailto:swift-corelibs-dev-boun...@swift.org>>
> Subject: Re: [swift-corelibs-dev] Adding type conversion capabilities to JSON 
> encode/decode
> 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 
> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Furldefense.proofpoint.com%2Fv2%2Furl%3Fu%3Dhttps-3A__na01.safelinks.protection.outlook.com_-3Furl-3Dhttps-253A-252F-252Fdeveloper.apple.com-252Fdocumentation-252Fswift-252Fdecodable-252F2894081-2Dinit-26data-3D02-257C01-257Cbrsneed-2540ebay.com-257C6290a819253b47b0eb2408d4efe454ae-257C46326bff992841a0baca17c16c94ea99-257C0-257C0-257C636397211330551372-26sdata-3DoLr1Q10-252BztzwG-252BCXpMinBzJNTwSy-252FjoBsKm9Glg1-252FxY-253D-26reserved-3D0%26d%3DDwMGaQ%26c%3Djf_iaSHvJObTbx-siA1ZOg%26r%3DgkRZBtsmKeGPCOlAIRJoOA%26m%3Dc3lYikOfd2-4q_nd_qMnJ4gXKIuKuxxoJRxIrIZc3Hw%26s%3Dh1azblXptqRwHqDQhejN9sSFa8dR-Gd8OkB7_6VwgNg%26e%3D&data=02%7C01%7Cbrsneed%40ebay.com%7Cebd9669255614ce4dccc08d4efef218c%7C46326bff992841a0baca17c16c94ea99%7C0%7C0%7C636397257717072726&sdata=TIZrCfocLCJGcfOj%2B9V2FEiXPSTKN4hnL1Rm03GqHvk%3D&reserved=0>
> 
> You can check Foundation source code (i.e., the URL struct) on how this can 
> be implemented.
> 
> Thanks,
> 
> Youming Lin
> IBM Cloud, Swift@IBM, Kitura developer
> Austin, TX
> GitHub: @youming-lin
> 
> <image002.gif>"Sneed, Brandon via swift-corelibs-dev" ---08/30/2017 03:07:05 
> PM---Hi Tony, I like the idea that the type itself is responsible for the 
> conversion. My own json encode
> 
> From: "Sneed, Brandon via swift-corelibs-dev" <swift-corelibs-dev@swift.org 
> <mailto:swift-corelibs-dev@swift.org>>
> To: Tony Parker <anthony.par...@apple.com <mailto:anthony.par...@apple.com>>
> Cc: "swift-corelibs-dev@swift.org <mailto:swift-corelibs-dev@swift.org>" 
> <swift-corelibs-dev@swift.org <mailto:swift-corelibs-dev@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-boun...@swift.org 
> <mailto:swift-corelibs-dev-boun...@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.par...@apple.com <mailto:anthony.par...@apple.com>> on behalf 
> of Tony Parker <anthony.par...@apple.com <mailto:anthony.par...@apple.com>>
> Date: Wednesday, August 30, 2017 at 11:30 AM
> To: "Sneed, Brandon" <brsn...@ebay.com <mailto:brsn...@ebay.com>>
> Cc: Itai Ferber <ifer...@apple.com <mailto:ifer...@apple.com>>, 
> "swift-corelibs-dev@swift.org <mailto:swift-corelibs-dev@swift.org>" 
> <swift-corelibs-dev@swift.org <mailto:swift-corelibs-dev@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@swift.org <mailto:swift-corelibs-dev@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: <ifer...@apple.com <mailto:ifer...@apple.com>> on behalf of Itai Ferber 
> <ifer...@apple.com <mailto:ifer...@apple.com>>
> Date: Wednesday, August 30, 2017 at 11:22 AM
> To: "Sneed, Brandon" <brsn...@ebay.com <mailto:brsn...@ebay.com>>
> Cc: "swift-corelibs-dev@swift.org <mailto:swift-corelibs-dev@swift.org>" 
> <swift-corelibs-dev@swift.org <mailto:swift-corelibs-dev@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@swift.org <mailto:swift-corelibs-dev@swift.org>
> https://lists.swift.org/mailman/listinfo/swift-corelibs-dev 
> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Furldefense.proofpoint.com%2Fv2%2Furl%3Fu%3Dhttps-3A__na01.safelinks.protection.outlook.com_-3Furl-3Dhttps-253A-252F-252Flists.swift.org-252Fmailman-252Flistinfo-252Fswift-2Dcorelibs-2Ddev-26data-3D02-257C01-257Cbrsneed-2540ebay.com-257C0e58a975be44418826d608d4efd427dc-257C46326bff992841a0baca17c16c94ea99-257C0-257C0-257C636397141865218008-26sdata-3DytYIqDtMesw4NnpUbFmiWF2-252FKfxlawG4YuVWPJd099Y-253D-26reserved-3D0%26d%3DDwMGaQ%26c%3Djf_iaSHvJObTbx-siA1ZOg%26r%3DgkRZBtsmKeGPCOlAIRJoOA%26m%3DViDSVPImta3StTVAcktby2PMF_-du5itzz47jo-tNHg%26s%3DrVZl8iT3jj1nzuDTCqZ1pkhQIZD3-Byi8PUj50swTUg%26e%3D&data=02%7C01%7Cbrsneed%40ebay.com%7C6290a819253b47b0eb2408d4efe454ae%7C46326bff992841a0baca17c16c94ea99%7C0%7C0%7C636397211330551372&sdata=GkxX7xyhtHr1zqISNmjeBhvOkVoZdOihXcaugXSK9tA%3D&reserved=0>
> _______________________________________________
> swift-corelibs-dev mailing list
> swift-corelibs-dev@swift.org <mailto:swift-corelibs-dev@swift.org>
> https://lists.swift.org/mailman/listinfo/swift-corelibs-dev 
> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Furldefense.proofpoint.com%2Fv2%2Furl%3Fu%3Dhttps-3A__na01.safelinks.protection.outlook.com_-3Furl-3Dhttps-253A-252F-252Flists.swift.org-252Fmailman-252Flistinfo-252Fswift-2Dcorelibs-2Ddev-26data-3D02-257C01-257Cbrsneed-2540ebay.com-257Cf2eba37a5b40474e09b108d4efd5372d-257C46326bff992841a0baca17c16c94ea99-257C0-257C0-257C636397146413883032-26sdata-3DC1-252F8MXq-252Fh7NHgyxeKDkcHDcigtQjSztCaAeUxBzYZ3g-253D-26reserved-3D0%26d%3DDwMGaQ%26c%3Djf_iaSHvJObTbx-siA1ZOg%26r%3DgkRZBtsmKeGPCOlAIRJoOA%26m%3DViDSVPImta3StTVAcktby2PMF_-du5itzz47jo-tNHg%26s%3DLQ0cgWtC9rXRTDLu0W58VIukWrsRssHsIMGb9U6Y0MU%26e%3D&data=02%7C01%7Cbrsneed%40ebay.com%7C6290a819253b47b0eb2408d4efe454ae%7C46326bff992841a0baca17c16c94ea99%7C0%7C0%7C636397211330551372&sdata=afQLw7%2FVip%2Bts1P60ALOHrTNap93519tWLjYzkS2o5Q%3D&reserved=0>
> _______________________________________________
> swift-corelibs-dev mailing list
> swift-corelibs-dev@swift.org <mailto:swift-corelibs-dev@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=
>  
> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Furldefense.proofpoint.com%2Fv2%2Furl%3Fu%3Dhttps-3A__na01.safelinks.protection.outlook.com_-3Furl-3Dhttps-253A-252F-252Furldefense.proofpoint.com-252Fv2-252Furl-253Fu-253Dhttps-2D3A-5F-5Flists.swift.org-5Fmailman-5Flistinfo-5Fswift-2D2Dcorelibs-2D2Ddev-2526d-253DDwIGaQ-2526c-253Djf-5FiaSHvJObTbx-2DsiA1ZOg-2526r-253DgkRZBtsmKeGPCOlAIRJoOA-2526m-253DViDSVPImta3StTVAcktby2PMF-5F-2Ddu5itzz47jo-2DtNHg-2526s-253DzRuNQ3NLxpfhFBewRTkoMWZnpvHlm6Ja-2Dot9-5FpwAgqI-2526e-253D-26data-3D02-257C01-257Cbrsneed-2540ebay.com-257C6290a819253b47b0eb2408d4efe454ae-257C46326bff992841a0baca17c16c94ea99-257C0-257C0-257C636397211330551372-26sdata-3DkUgv-252B3QRVpUH5JGBclTqYHheS-252FfaDPIWTrTk-252F-252BX8J-252Bs-253D-26reserved-3D0%26d%3DDwMGaQ%26c%3Djf_iaSHvJObTbx-siA1ZOg%26r%3DgkRZBtsmKeGPCOlAIRJoOA%26m%3Dc3lYikOfd2-4q_nd_qMnJ4gXKIuKuxxoJRxIrIZc3Hw%26s%3DlhWK6MIAPUmU4rsIhtD7P7EgacPwfGk17SvpQdMJogc%26e%3D&data=02%7C01%7Cbrsneed%40ebay.com%7Cebd9669255614ce4dccc08d4efef218c%7C46326bff992841a0baca17c16c94ea99%7C0%7C0%7C636397257717072726&sdata=jJucdx3j9pb2ylcsHYaVAtze%2B%2BQWr%2F%2Bm2GpBRlHaBTk%3D&reserved=0>
>  
> 
> 
> 
> 
> 
> 
> 
> 
>  

_______________________________________________
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev

Reply via email to