Kode Swift: Tidak dapat mendekode kamus jenis [String: Any] atau [String: Decodable]

-3
Pilih

Dalam penginisialisasi ubahsuaian, saya ingin mendekode kamus dari JSON dan kemudian menetapkan nilainya ke properti di kelas. Yang mengejutkan saya, kompilator tidak mengizinkan saya untuk memecahkan kode kamus, saya mendapatkan kesalahan:

Dalam penginisialisasi khusus saya, saya ingin mendekode kamus dari JSON dan kemudian menetapkan nilainya ke properti di kelas. Yang mengejutkan saya, kompiler tidak mengizinkan saya untuk memecahkan kode kamus, saya mendapatkan kesalahan:
Value of protocol type 'Any' cannot conform to 'Decodable'; only struct/enum/class types can conform to protocols
Value of protocol type 'Any' cannot conform to 'Decodable'; only struct/enum/class types can conform to protocols Nilai tipe protokol 'Any' tidak dapat mengikuti 'Decodable'; hanya tipe struct/enum/class yang dapat mengikuti protokol

Jika saya mencoba memecahkan kode kamus jenis[String: Decodable] pesan kesalahan mengatakan:

Jika saya mencoba mendekode kamus jenis[String: Decodable] pesan kesalahan mengatakan:
Value of protocol type 'Decodable' cannot conform to 'Decodable'; only struct/enum/class types can conform to protocols
Value of protocol type 'Decodable' cannot conform to 'Decodable'; only struct/enum/class types can conform to protocols Nilai jenis protokol 'Decodable' tidak dapat mengikuti 'Decodable'; hanya tipe struct/enum/class yang dapat mengikuti protokol

Penginisialisasi saya terlihat seperti ini:

Penginisialisasi saya terlihat seperti ini:
public let total: Int

required init(from decoder: Decoder) throws {
    let container=try decoder.container(keyedBy: CodingKeys.self)
    ...
    if let dict=try container.decodeIfPresent([String: Any].self, forKey: .tracks),
           let value=dict["total"] as? Int { // Error is displayed at this line
        total=value
    } else {
        total=0
    }
    ...
}
public let total: Int required init(from decoder: Decoder) throws { let container=try decoder.container(keyedBy: CodingKeys.self) ... if let dict=try container.decodeIfPresent([String: Any].self, forKey: .tracks), let value=dict["total"] as? Int { // Error is displayed at this line total=value } else { total=0 } ... } publik biarkan total: Int init yang diperlukan (dari decoder: Decoder) melempar { let container=coba decoder.container (keyedBy: CodingKeys.self) ... jika let dict=coba container.decodeIfPresent ([String: Any] .self, forKey: .tracks), biarkan nilai=dict["total"] sebagai? Int {// Error ditampilkan di baris ini total=nilai } lain { total=0 } ... }

Ketika saya mencari jawabannya, saya menemukan this answer dan menurutnya kode di atas seharusnya tidak menimbulkan masalah.

Ketika saya mencari jawaban saya menemukan this answer jawaban ini dan menurutnya kode di atas seharusnya tidak menimbulkan masalah.

Sumber

swift ios codable

-Larme

1 -Larme

1 Menjawab
1
Pilih

Yang Anda cari adalah nestedContainer. Ini membantu Anda"melewati"level hierarki di JSON Anda. Ie: mari kita bayangkan bahwa dalam kode Anda, semuanya berada di level yang sama (satu struct), tetapi di JSON, tidak, ada sub kamus.

Untuk tujuan pengujian, JSON Anda mungkin terlihat seperti:

{
   "title":"normal",
   "tracks": {
                  "name":"myName",
                  "total": 3
              }
}

Jika kita menginginkan model kita:

struct TestStruct: Codable {
    let title: String
    let name: String
    let total: Int
}

Kita perlu menggunakan nestedContainer(keyedBy: forKey:):

extension TestStruct {
    enum TopLevelKeys: String, CodingKey {
        case title
        case tracks
    }
    
    enum NestedLevelCodingKeys: String, CodingKey {
        case name
        case total
    }
    
    init(from decoder: Decoder) throws {
        let container=try decoder.container(keyedBy: TopLevelKeys.self)
        self.title=try container.decode(String.self, forKey: .title)
        let subcontainer=try container.nestedContainer(keyedBy: NestedLevelCodingKeys.self, forKey: TopLevelKeys.tracks)
        self.name=try subcontainer.decode(String.self, forKey: .name)
        self.total=try subcontainer.decode(Int.self, forKey: .total) //You can use here a `decodeIfPresent()` if needed, use default values, etc.

    }
}

Dalam sampel Anda, Anda menggunakan decodeIfPresent() untuk subdiksi. Tidak jelas apakah itu untuk tujuan pengujian, atau jika sub kamus terkadang tidak ada. Jika itu masalahnya dan Anda dapat memiliki JSON seperti ini:

{
   "title":"normal"
} 

Lalu, sebelum memanggil nestedContainer(keyedBy: forKey:), gunakan if container.contains(TopLevelKeys.tracks) {} dan menetapkan nilai default jika diperlukan di else kasus.

Sumber

Anda Mungkin Menarik

© 2021   Pemrograman.Net