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")
}

      

+3


source to share


1 answer


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).

0


source







All Articles