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
'sDecodable
implementation expects an array of key value pairs, i.e.: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 randomDecodable
value into a string. It could have been made to check forRawRepresentable
withRawValue == String
, but it wasn't.One thing that it does check for though, is
CodingKeyRepresentable
, if you just conformLg
to that, then you can decode a JSON dictionary correctly.Note that I also conformed it to
CodingKey
to make it easier to write thecodingKey
property required byCodingKeyRepresentable
.