[swift-users] Decode a JSON object of unknown format into a Dictionary with Decodable in Swift 4

Itai Ferber iferber at apple.com
Mon Jul 3 10:57:02 CDT 2017


Hi Kevin,

You’re right — this is one of the limitations of the box design 
here. One thing we can do is expose the underlying boxed value as a 
`KeyedDecodingContainerProtocol` existential value using an accessor on 
the box so you can down-cast.

However, it shouldn’t be necessary to add any methods to 
`_JSONEncoder` or `_JSONDecoder` to support this. What are you trying to 
do?

— Itai

On 1 Jul 2017, at 9:07, Kevin Wooten wrote:

> Itai,
>
> I tried copying JSONEncoder.swift from the swift repo and implementing 
> the `Unevaluated` type in it.  It doesn’t appear to be a workable 
> solution due to the fact that the `KeyedEncodingContainer` type 
> erasure box is the only value returned from `container(keyedBy:)`. 
> This means that any extra methods implemented inside `JSONDecoder` (or 
> `_JSONDecoder` in this case) can ever be publicly accessed (even with 
> casting) unless the type erasure box also includes an equivalent 
> method.
>
> How do you propose getting around this?  Seems like the design of this 
> might be a bit limiting when considering extension/enhancement in user 
> specific code.
>
>
>> On Jun 29, 2017, at 12:47 PM, Itai Ferber <iferber at apple.com> wrote:
>>
>> Hi Kevin,
>>
>>> On Jun 29, 2017, at 12:30 PM, Kevin Wooten via swift-users 
>>> <swift-users at swift.org <mailto:swift-users at swift.org>> wrote:
>>>
>>>> Hi Jon,
>>>>
>>>> I just joined this mailing list and have tried to catch up on the
>>>> history of this thread, so please excuse me if I’ve missed 
>>>> something.
>>>>
>>>> I’m sorry the Codable API at the moment does not answer your 
>>>> needs —
>>>> you’re clearly not the only one who’s run into this, so let’s 
>>>> see
>>>> how we can work together to make the API better for everyone.
>>>> For one thing, in the case of grabbing a subtree of JSON as
>>>> "unevaluated" or "unmapped" (as it appears to be in the metadata 
>>>> case),
>>>> it should be fairly simple to add a `JSONDecoder.UnevaluatedJSON` 
>>>> type
>>>> that will allow you to essentially decode that part of the tree as 
>>>> an
>>>> `Any`. `JSONDecoder` would have knowledge of this type and would be 
>>>> able
>>>> to return the subtree inside of it — you’d decode a property as
>>>> `JSONDecoder.UnevaluatedJSON.self` and access the contents through 
>>>> `var
>>>> value: Any?`, or something similar. This would be simple additive 
>>>> API,
>>>> which although might not make it in the upcoming betas, should be 
>>>> fairly
>>>> simple introduce. Would this solve that use case?
>>>>
>>>> We’re also working on improving `NSISO8601DateFormatter`. I 
>>>> don’t
>>>> think I saw it in any of your emails — what specific use case are 
>>>> you
>>>> looking for that it doesn’t at the moment support?
>>>>
>>>> — Itai
>>>
>>>
>>> Itai,
>>>
>>> Is this a formal solution that is going to be implemented? This 
>>> would solve just about every issue I currently have with Decodable.
>> I can’t make any promises at the moment — we’ve got a lot of 
>> high-priority things to fix before the Swift 4.0 release. However, 
>> this is something I’d certainly like to put through API review and 
>> eventually release, since this is clearly something that would be 
>> beneficial to a lot of our users.
>>
>>> Two points…
>>>
>>> 1) Putting it on `JSONDecoder` seems dubious since you’d only have 
>>> access to `Decoder` (although conditional casting could solve that). 
>>> It seems adding the method to `Decoder` and using 
>>> `Decoder.Unevaluated.self` as the requested type, would be more 
>>> useful. A user could then conditionally cast that value to things 
>>> like `[String: Any]` and possibly use its contents generically.
>> Putting that on Decoder would require all Decoders to have an 
>> "unevaluated type" representation, which may not be appropriate for 
>> all formats.
>> Since this is very often a request when working with 3rd-party APIs 
>> which you don’t control (and are rarely offered in more than one 
>> format, if that), putting this directly on JSONDecoder seems 
>> reasonable — you’d only really expect this representation if 
>> you’re decoding from JSON; if you’re encoding to/from a different 
>> format, you’re likely in control of the data in those formats.
>>
>>> 2) Matching it with an equivalent on `Encoder` would be great as 
>>> well.  We take in JSON that has “metaData” like one 
>>> aforementioned exampled. We then have to send back the equivalent 
>>> metadata during a subsequent update; without ever inspecting or 
>>> altering the unevaluated data. Being able encode a 
>>> `Decoder.Unevaluated` would solve that problem as well.
>> Yes, we’d add an equivalent type on encode as well.
>>
>>>
>>>
>>> _______________________________________________
>>> swift-users mailing list
>>> swift-users at swift.org <mailto:swift-users at swift.org>
>>> https://lists.swift.org/mailman/listinfo/swift-users
>>


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20170703/8cce75e3/attachment.html>


More information about the swift-users mailing list