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      

Hacking with Swift is sponsored by RevenueCat

SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure your entire paywall view without any code changes or app updates.

Learn more here

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.