UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

Decoding JSON consisting of sub-classes

Forums > Swift

Dear all,

I have run into the following issue: I am trying to decode a json file that consists of different sub-classes with different information degrees. Let me explain with a simplified example:

Class

class Vehicle: Codable {
    var currentlyDrives: Bool
    var speed: Double

    init(drives: Bool, speed: Double) {
        self.currentlyDrives = drives
        self.speed = speed
    }
}

class Car: Vehicle {
    var numberOfPassengers: Int

    init(drives: Bool, speed: Double, numPax: Int) {
        self.numberOfPassengers = numPax
        super.init(drives: drives, speed: speed)
    }

    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        numberOfPassengers = try container.decode(Int.self, forKey: .numberOfPassengers)
        try super.init(from: decoder)
    }

    override func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(numberOfPassengers, forKey: .numberOfPassengers)
        try super.encode(to: encoder)
    }

    enum CodingKeys: String, CodingKey {
        case numberOfPassengers
    }
}

If I am creating instances of both "Vehicles" and "Cars" and putting everything in an array, I have no problem encoding to a proper JSON file (including all properties of Cars if we have a car and only properties of vehicles if we have a vehicle (see below)).

let car = Car(drives: true, speed: 123, numPax: 5)
let bike = Vehicle(drives: true, speed: 12)

var array = [Vehicle]()
array.append(car)
array.append(bike)

let encoded = try! JSONEncoder().encode(array)
print(String(data: encoded, encoding: .utf8)!)

The above prints a proper JSON as follows with car having the additional "numberOfPassengers" property:

[{"currentlyDrives":true,"numberOfPassengers":5,"speed":123},{"currentlyDrives":true,"speed":12}]

When decoding I am able to read back all Vehicles without a problem. However what I would like to achieve is reading back a vehicle as a car if it is one (i.e. being able to read "numberOfPassengers".

Do you have any idea how this would be achievable?

Many thanks in advance and best regards, Julian

3      

What I want to add: when I have an array of Cars, I habe no problem reading back an array of Cars with all properties.

But what I really want to achieve is encoding an array of vehicles (which can be car OR vehicle) and then being able to cast as the actual type.

i hope this makes sense, otherwise happy to provide another example.

Any ideas are highly appreciated.

Stay healthy!

3      

TAKE YOUR SKILLS TO THE NEXT LEVEL If you like Hacking with Swift, you'll love Hacking with Swift+ – it's my premium service where you can learn advanced Swift and SwiftUI, functional programming, algorithms, and more. Plus it comes with stacks of benefits, including monthly live streams, downloadable projects, a 20% discount on all books, and free gifts!

Find out more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.