I just tried this:
let test = "{ \"de\": \"Bisasam\", \"en\": \"Bulbasaur\" }"
let data = test.data(using: .utf8)!
do {
let result = try JSONDecoder().decode([String: String].self, from: data)
print("") // breakpoint here works
} catch {
print("")
}
This works fine, however when I try to do this instead:
enum Lg: String, CaseIterable, Decodable {
case deutsch = "de"
case english = "en"
}
let test = "{ \"de\": \"Bisasam\", \"en\": \"Bulbasaur\" }"
let data = test.data(using: .utf8)!
do {
let result = try JSONDecoder().decode([Lg: String].self, from: data)
print("")
} catch {
print("") // breakpoint here
}
With this error:
▿ DecodingError ▿ typeMismatch : 2 elements
- .0 : Swift.Array ▿ .1 : Context
- codingPath : 0 elements
- debugDescription : "Expected to decode Array but found a dictionary instead."
- underlyingError : nil
What am I doing wrong?
Thanks for your help
When you use a non-String
non-Int
type as the dictionary key, Dictionary
's Decodable
implementation expects an array of key value pairs, i.e.:
["de", "foo", "en": "bar"]
This decodes to [.deutsch: "foo", .english: "bar"]
.
JSON keys can only be strings after all, and the Decodable
implementation doesn't know how to convert a random Decodable
value into a string. It could have been made to check for RawRepresentable
with RawValue == String
, but it wasn't.
One thing that it does check for though, is CodingKeyRepresentable
, if you just conform Lg
to that, then you can decode a JSON dictionary correctly.
Conforming a type to
CodingKeyRepresentable
lets you opt in to encoding and decodingDictionary
values keyed by the conforming type to and from a keyed container, rather than encoding and decoding the dictionary as an unkeyed container of alternating key-value pairs.
extension Lg: CodingKeyRepresentable, CodingKey {
init?<T>(codingKey: T) where T : CodingKey {
self.init(rawValue: codingKey.stringValue)
}
var codingKey: CodingKey {
self
}
}
Note that I also conformed it to CodingKey
to make it easier to write the codingKey
property required by CodingKeyRepresentable
.