Swift Kodlanabilir Sözlük
Kodlanabilir hale gelme konusunda sorun yaşıyorum. Herhangi bir yardım çok takdir edilecektir. Oyun alanımda aşağıdakiler var
JSON dosyamdan örnek. Çok daha fazla öğeye sahip, daha küçük bir alt kümeye indirgedi.
{
"metadata" : {
"generated" : {
"timestamp" : 1549331723,
"date" : "2019-02-04 20:55:23"
}
},
"data" : {
"CA" : {
"country-id" : 25000,
"country-iso" : "CA",
"country-eng" : "Canada",
"country-fra" : "Canada",
"date-published" : {
"timestamp" : 1544561785,
"date" : "2018-12-11 15:56:25",
"asp" : "2018-12-11T15:56:25.4141468-05:00"
}
},
"BM" : {
"country-id" : 31000,
"country-iso" : "BM",
"country-eng" : "Bermuda",
"country-fra" : "Bermudes",
"date-published" : {
"timestamp" : 1547226095,
"date" : "2019-01-11 12:01:35",
"asp" : "2019-01-11T12:01:35.4748399-05:00"
}
}
}
}
Quicktype uygulamasından. Datum için bir sözlük oluşturdu. Json'un yapılandırılma şekli, ülke kısaltmasının bir etiketi yoktur.
import Foundation
// MARK: - Welcome
struct Welcome: Codable {
let metadata: Metadata?
let data: [String: Datum]?
}
// MARK: - Datum
struct Datum: Codable {
let countryID: Int?
let countryISO, countryEng, countryFra: String?
let datePublished: DatePublished?
enum CodingKeys: String, CodingKey {
case countryID = "country-id"
case countryISO = "country-iso"
case countryEng = "country-eng"
case countryFra = "country-fra"
case datePublished = "date-published"
}
}
// MARK: - DatePublished
struct DatePublished: Codable {
var timestamp: Int
var date, asp: String
}
// MARK: - Metadata
struct Metadata: Codable {
var generated: Generated
}
// MARK: - Generated
struct Generated: Codable {
var timestamp: Int
var date: String
}
// MARK: - Encode/decode helpers
class JSONNull: Codable, Hashable {
public static func == (lhs: JSONNull, rhs: JSONNull) -> Bool {
return true
}
public var hashValue: Int {
return 0
}
public func hash(into hasher: inout Hasher) {
// No-op
}
public init() {}
public required init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if !container.decodeNil() {
throw DecodingError.typeMismatch(JSONNull.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for JSONNull"))
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encodeNil()
}
}
Kodumdan json dosyasını yükleyebiliyorum, buradaki verileri sözlükle nasıl işleyeceğimi ve ülkenin ülke kısaltması için bir adı olmadığını bilmiyorum.
guard let url = Bundle.main.url(forResource: "data", withExtension: "json") else { return 0 }
let jsonData = try Data(contentsOf: url)
Not: Bu, önceki sorumun devamı niteliğindedir : Swift Kodlanabilir Ayrıştırma tuşuNotFound
Yanıtlar
Veri modelleriniz zaten doğru bir şekilde tanımlanmıştır (ancak, bazı ad değişikliklerini ve özelliklerden değişkenliği / isteğe bağlılığı kaldırmanızı öneririm).
JSON'u ayrıştırdıktan sonra Dictionary, anahtarlar aslında country-isoanahtarın altındaki değerin bir parçası olduğu için, ' yi tutmanıza gerek yoktur .
Dolayısıyla, Rootnesnenizin kodunu çözdükten sonra , basitçe tutmanızı öneririm root.data.values, bu da size Array<CountryData>daha sonra kolayca idare edebileceğiniz verir .
struct Root: Codable {
let data: [String: CountryData]
}
struct CountryData: Codable {
let countryID: Int
let countryISO, countryEng, countryFra: String
let datePublished: DatePublished
enum CodingKeys: String, CodingKey {
case countryID = "country-id"
case countryISO = "country-iso"
case countryEng = "country-eng"
case countryFra = "country-fra"
case datePublished = "date-published"
}
}
// MARK: - DatePublished
struct DatePublished: Codable {
let timestamp: Int
let date, asp: String
}
do {
let root = try JSONDecoder().decode(Root.self, from: countryJson.data(using: .utf8)!)
let countries = root.data.values
print(countries)
} catch {
error
}