Codable / Decodable should decode array with strings
Why are Array names not decoded?
Prepared for playground, just slide this into your playground.
import Foundation
struct Country : Decodable {
enum CodingKeys : String, CodingKey {
case names
}
var names : [String]?
}
extension Country {
public init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
names = try values.decode([String]?.self, forKey: .names)!
}
}
let json = """
[{
"names":
[
"Andorre",
"Andorra",
"アンドラ"
]
},{
"names":
[
"United Arab Emirates",
"Vereinigte Arabische Emirate",
"Émirats Arabes Unis",
"Emiratos Árabes Unidos",
"アラブ首長国連邦",
"Verenigde Arabische Emiraten"
]
}]
""".data(using: .utf8)!
let decoder = JSONDecoder()
do {
let countries = try decoder.decode([Country].self, from: json)
countries.forEach { print($0) }
} catch {
print("error")
}
source to share
You have defined names
as an optional property Country
. If your intention is that this key cannot be present in the JSON then use decodeIfPresent
:
extension Country {
public init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
names = try values.decodeIfPresent([String].self, forKey: .names)
}
}
This method returns nil
if the container has no value associated with the key, or if the value is null.
But you can actually just omit your custom init(from decoder: Decoder)
(s enum CodingKeys
), because this is the default behavior and will be synthesized automatically.
Note. An implicit variable is error
defined in any statement catch
like this
} catch {
print(error.localizedDescription)
}
may be more informative than simple print("error")
(although not in this particular case).
source to share