New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SR-5311] Allow JSONDecoder to somehow provide loose JSON structure #47886
Comments
cc @itaiferber |
We've had multiple requests for this type of unevaluated JSON, both on encode and on decode. Definitely on our plans, but at this point it's a bit of an additive feature. |
@swift-ci create |
Comment by Hannes Oud (JIRA) Cool, thanks for the feedback! |
This seems like a huge oversight and it's causing real problems for me right now. I have to accurately describe the structure of a complicated sub-object simply because it's impossible to decode it as a There's also no way to implement this in |
Eridius (JIRA User) We're still interested in offering this, but haven't had the bandwidth to design and implement what the API might look like. See also some of the discussion here. This is possible to work around in the meantime by creating a As for asking a |
How do I decode a JSON enum? How would I implement |
Eridius (JIRA User) Yes, the model for attempting to decode one of multiple disparate types is to try them in turn until one succeeds. |
To be clear, asking a given |
There's 2 basic types of decoders: self-describing ones (like JSON) and non-described one (where the interpretation of the input depends on the type you ask for). Self-describing ones should be able to declare their type, the others obviously can't. One possible solution here is to have another protocol Then we could have The alternative is to just have the decoder containers have something like |
BTW where does |
Eridius (JIRA User) What does
|
I was thinking that e.g. let value = try container.decode(container.type(forKey: key), forKey: key) though I apparently hadn't actually thought it through because that is a little awkward and it would probably be simpler just to add a single method that means "return the underlying value without decoding it as anything". If |
Yeah, unfortunately, there are two main issues there:
The best solution at the moment, I think, would be to introduce struct JSONDecoder {
struct UnevaluatedJSON : Decodable {
let value: Any
init(from decoder: Decoder) throws { throw /* can only be decoded by JSONDecoder */ }
}
}
|
Also, all the primitive types are let values: [Any] = [
true,
(1 as Int8),
(1 as Int16),
(1 as Int32),
(1 as Int64),
(1 as Int),
(1 as UInt8),
(1 as UInt16),
(1 as UInt32),
(1 as UInt64),
(1 as UInt),
(1 as Float),
(1 as Double),
"hello"
]
for value in values {
print("\(type(of: value)) is Codable: \(value is Codable)")
} produces Bool is Codable: true
Int8 is Codable: true
Int16 is Codable: true
Int32 is Codable: true
Int64 is Codable: true
Int is Codable: true
UInt8 is Codable: true
UInt16 is Codable: true
UInt32 is Codable: true
UInt64 is Codable: true
UInt is Codable: true
Float is Codable: true
Double is Codable: true
String is Codable: true |
1. |
Are the primitives conforming to |
No, it's definitely been this way since 4.0. If you run the code above, it returns |
Hmm you're right, it prints |
Hmm — looks like the documentation lists |
Filed as rdar://problem/37547329. |
Excellent, thanks! However, back to your actual points:
|
1. I suspect the best solution is probably to inspect the underlying type of the |
I think many people are surprised in practice by the result of the boxed type inside of an Also, you can't conform a type to the same protocol multiple times using conditional conformance, which means we could either have |
Dammit. That limitation pretty much requires us to use some sort of type-erased struct as the array/dictionary value simply so it can conform to |
Regardless, I don't think
There are some other issues at hand, but in general, I think that going the
|
It doesn't double the API. Protocol inheritance means you get to re-use most of it. I think there is a bit of confusion here with regards to In any case, the |
Here's the issue:
|
Ah yes. So I guess you wouldn't have either decodable inherit from the other, and instead you'd just extend the typed decoder containers to have one extra |
I think that still undesirably splits the API based on the format. Now to support all formats, you need to conform with both I agree that |
No you'd conform to either |
Additional Detail from JIRA
md5: 5eb72b813df2f976700cdaab0d43900e
Issue Description:
I have an API, which is mostly strongly typed, but has some part that has a JSON dictionary, with arbitrary elements, which could be used for debugging purposes. At first I tried to map this to my Decodable type via a property of Dictionary type
String: Decodable
but this didn't work, because swift needs more type info. I then came up with the attached enum for representing a random JSON structure, sort of similar to whatNSJSONSerialization
provides (see below).I assume the
JSONDecoder
has a representation of this structure already.Could something like this be obtained from the
JSONDecoder
somehow?Suggestion would be let
Decoder
have atypealias CanonicalStructure = JSONValue
and a the singleValueContainer have adecoder.decodeCanonicalStructure() throws
?Here's my quick idea for such a structure https://gist.github.com/hannesoid/10a35895e4dc5d6f1bb6428f7d4d23a5
The text was updated successfully, but these errors were encountered: