NEW: Start my new Ultimate Portfolio App course with a free Hacking with Swift+ trial! >>

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

   

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!

   

Hacking with Swift is sponsored by Fernando Olivares

SPONSORED Would you describe yourself as knowledgeable, but struggling when you have to come up with your own code? Fernando Olivares has a new book containing iOS rules you can immediately apply to your coding habits to see dramatic improvements, while also teaching applied programming fundamentals seen in refactored code from published apps.

Try the book!

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.