Heterogeenisen JSONin dekoodaus
Käsittele polymorfisia ja dynaamisia JSON-rakenteita.
Heterogeenisen JSONin dekoodaus on ilmainen Swift Academy-oppitunti CoddyKitissä. Tämä on oppitunti 4/4. Voit lukea tästä oppimispolusta kokonaan mitkä tahansa 3 oppituntia ilmaiseksi — sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä käytännön harjoittelun sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Oppitunti kuuluu Swift Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Swift Academy-kurssilla on yhteensä 4 oppituntia.
Mitä heterogeeninen JSON tarkoittaa
Jotkin API:t palauttavat taulukoita, joiden objektit ovat rakenteeltaan erilaisia ja joiden tyyppi ilmaistaan type-kentällä. Niiden dekoodaaminen yhdeksi Swift-tyypiksi edellyttää, että tarkistatte ensin tämän erottelukentän.
import Foundation
let json = "[{\"type\":\"text\",\"value\":\"hi\"},{\"type\":\"number\",\"value\":42}]"
print("Each element carries a type discriminator")Mallintaminen enumeraatiolla
Luonteva Swift-malli on enumeraatio, jolla on liitettyjä arvoja — yksi tapaus kutakin JSON-rakennetta varten. Dekooderi valitsee tapauksen erottelukentän perusteella.
import Foundation
enum Block {
case text(String)
case number(Int)
}
print("Enum models the variants")Erottelukentän määrittäminen
Lisätkää CodingKeys-enumeraatio, joka sisältää erottelukentän (tässä type) sekä tarvitsemanne hyötykuorman avaimet.
import Foundation
enum CodingKeys: String, CodingKey {
case type
case value
}
print(CodingKeys.type.stringValue, CodingKeys.value.stringValue)Erottelukentän lukeminen
Dekoodatkaa init(from:)-metodissa ensin type-merkkijono ja valitkaa sitten sen perusteella oikea hyötykuorma switch-rakenteella.
import Foundation
enum Block: Decodable {
case text(String)
case number(Int)
enum CodingKeys: String, CodingKey { case type, value }
init(from decoder: Decoder) throws {
let c = try decoder.container(keyedBy: CodingKeys.self)
let type = try c.decode(String.self, forKey: .type)
switch type {
case "text": self = .text(try c.decode(String.self, forKey: .value))
case "number": self = .number(try c.decode(Int.self, forKey: .value))
default: throw DecodingError.dataCorruptedError(forKey: .type, in: c, debugDescription: "unknown type")
}
}
}
let b = try JSONDecoder().decode(Block.self, from: "{\"type\":\"text\",\"value\":\"hi\"}".data(using: .utf8)!)
if case let .text(s) = b { print(s) }Sekamuotoisen taulukon dekoodaus
Kun enumeraatio on Decodable, lauseke [Block].self dekoodaa kokonaisen taulukon erimuotoisia alkioita yhdellä kutsulla.
import Foundation
enum Block: Decodable {
case text(String)
case number(Int)
enum CodingKeys: String, CodingKey { case type, value }
init(from decoder: Decoder) throws {
let c = try decoder.container(keyedBy: CodingKeys.self)
switch try c.decode(String.self, forKey: .type) {
case "text": self = .text(try c.decode(String.self, forKey: .value))
case "number": self = .number(try c.decode(Int.self, forKey: .value))
default: throw DecodingError.dataCorruptedError(forKey: .type, in: c, debugDescription: "unknown")
}
}
}
let json = "[{\"type\":\"text\",\"value\":\"hi\"},{\"type\":\"number\",\"value\":42}]"
let blocks = try JSONDecoder().decode([Block].self, from: json.data(using: .utf8)!)
print(blocks.count)Tuloksen käsittely pattern matchingilla
Dekoodauksen jälkeen voitte käsitellä jokaista muunnelmaa tyyppiturvallisesti käymällä enumeraation tapaukset läpi switch-rakenteella.
import Foundation
enum Block: Decodable {
case text(String)
case number(Int)
enum CodingKeys: String, CodingKey { case type, value }
init(from decoder: Decoder) throws {
let c = try decoder.container(keyedBy: CodingKeys.self)
switch try c.decode(String.self, forKey: .type) {
case "text": self = .text(try c.decode(String.self, forKey: .value))
case "number": self = .number(try c.decode(Int.self, forKey: .value))
default: throw DecodingError.dataCorruptedError(forKey: .type, in: c, debugDescription: "unknown")
}
}
}
let json = "[{\"type\":\"text\",\"value\":\"hi\"},{\"type\":\"number\",\"value\":42}]"
for b in try JSONDecoder().decode([Block].self, from: json.data(using: .utf8)!) {
switch b {
case .text(let s): print("text:", s)
case .number(let n): print("number:", n)
}
}Sisäkkäiset hyötykuormat
Kun muunnelmat sisältävät monipuolisempaa dataa, dekoodatkaa jokaista tapausta varten sisäkkäinen Codable-rakenne yksittäisen arvon sijaan.
import Foundation
struct ImagePayload: Decodable { var url: String; var width: Int }
enum Block: Decodable {
case image(ImagePayload)
enum CodingKeys: String, CodingKey { case type }
init(from decoder: Decoder) throws {
let c = try decoder.container(keyedBy: CodingKeys.self)
switch try c.decode(String.self, forKey: .type) {
case "image": self = .image(try ImagePayload(from: decoder))
default: throw DecodingError.dataCorruptedError(forKey: .type, in: c, debugDescription: "unknown")
}
}
}
let json = "{\"type\":\"image\",\"url\":\"a.png\",\"width\":100}"
if case let .image(p) = try JSONDecoder().decode(Block.self, from: json.data(using: .utf8)!) {
print(p.url, p.width)
}Tuntemattomien tyyppien hallinta hallitusti
Tuntemattomien erottelukenttien aiheuttaman virheen sijaan voitte yhdistää ne varatapahtumaan, jolloin uudet palvelimen tyypit eivät koskaan kaada asiakassovellusta.
import Foundation
enum Block: Decodable {
case text(String)
case unknown
enum CodingKeys: String, CodingKey { case type, value }
init(from decoder: Decoder) throws {
let c = try decoder.container(keyedBy: CodingKeys.self)
switch try c.decode(String.self, forKey: .type) {
case "text": self = .text(try c.decode(String.self, forKey: .value))
default: self = .unknown
}
}
}
let b = try JSONDecoder().decode(Block.self, from: "{\"type\":\"video\"}".data(using: .utf8)!)
if case .unknown = b { print("fell back to unknown") }Hyvän erottelukentän valitseminen
Erottelukentän tulisi olla vakaa ja pakollinen kenttä. Tunnettujen tyyppinimien String-enumeraatio pitää switch-rakenteen kattavana ja helposti luettavana.
import Foundation
enum Kind: String, Decodable { case text, number }
let data = "\"text\"".data(using: .utf8)!
let k = try JSONDecoder().decode(Kind.self, from: data)
print(k == .text)Polymorfisten arvojen koodaus
Jotta arvon voisi koodata ja dekoodata edestakaisin, toteuttakaa myös encode(to:): kirjoittakaa erottelukenttä ja muunnelman hyötykuorma takaisin.
import Foundation
enum Block: Encodable {
case text(String)
case number(Int)
enum CodingKeys: String, CodingKey { case type, value }
func encode(to encoder: Encoder) throws {
var c = encoder.container(keyedBy: CodingKeys.self)
switch self {
case .text(let s):
try c.encode("text", forKey: .type)
try c.encode(s, forKey: .value)
case .number(let n):
try c.encode("number", forKey: .type)
try c.encode(n, forKey: .value)
}
}
}
let data = try JSONEncoder().encode(Block.number(42))
print(String(data: data, encoding: .utf8)!)Kokonaisuuden kokoaminen
Täysi polymorfinen malli dekoodaa sekamuotoisen taulukon, käsittelee jokaisen muunnelman switch-rakenteella ja voi koodata datan takaisin samaan muotoon — vankka malli joustaville API-rajapinnoille.
import Foundation
enum Block: Codable {
case text(String)
case number(Int)
enum CodingKeys: String, CodingKey { case type, value }
init(from d: Decoder) throws {
let c = try d.container(keyedBy: CodingKeys.self)
switch try c.decode(String.self, forKey: .type) {
case "text": self = .text(try c.decode(String.self, forKey: .value))
default: self = .number(try c.decode(Int.self, forKey: .value))
}
}
func encode(to e: Encoder) throws {
var c = e.container(keyedBy: CodingKeys.self)
switch self {
case .text(let s): try c.encode("text", forKey: .type); try c.encode(s, forKey: .value)
case .number(let n): try c.encode("number", forKey: .type); try c.encode(n, forKey: .value)
}
}
}
let blocks: [Block] = [.text("hi"), .number(7)]
let data = try JSONEncoder().encode(blocks)
print(try JSONDecoder().decode([Block].self, from: data).count)Pikatarkistus: heterogeeninen JSON
Testatkaa, miten hyvin ymmärrätte polymorfista dekoodausta.
Kertaus: heterogeenisen JSON-datan dekoodaus
Opitte käsittelemään polymorfisia hyötykuormia:
- Mallintakaa muunnelmat enumeraationa, jolla on liitettyjä arvoja.
- Dekoodatkaa
init(from:)-metodissa erottelukenttä ja valitkaa sitten oikea tapaus switch-rakenteella. - Dekoodatkaa sekamuotoiset taulukot muodolla
[Enum].selfja käsitelkää tuloksia pattern matchingilla. - Lisätkää varatapaus tuntemattomille tyypeille ja toteuttakaa
encode(to:)edestakaista koodausta varten.
Opi Swift tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 122
- Oppitunnit
- 409
Usein kysytyt kysymykset
Onko oppitunti ”Heterogeenisen JSONin dekoodaus” ilmainen?
Kyllä — voit lukea täällä verkossa kokonaan ilmaiseksi mitkä tahansa Swift Academy-oppimispolun 3 oppituntia, myös oppitunnin “Heterogeenisen JSONin dekoodaus”. Sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä interaktiiviset harjoitukset sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Swift Academy-kurssilla on yhteensä 4 oppituntia.
Mitä opin oppitunnilla ”Heterogeenisen JSONin dekoodaus”?
Käsittele polymorfisia ja dynaamisia JSON-rakenteita. Harjoittelet Swift Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni Swift Academy-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin Swift Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 4/4.
Kuinka kauan ”Heterogeenisen JSONin dekoodaus”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä Swift Academy-oppitunnilla?
Kyllä. Jokainen Swift Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- CodingKeys nimien uudelleennimeämiseen
- Avainten ja päivämäärien dekoodausstrategiat
- Manuaaliset encode(to:)- ja init(from:)-toteutukset
- Heterogeenisen JSONin dekoodaus