Robert
Robert

Reputation: 545

Encoding nested object

I have PalletScanHelper class with two structs - MovementScan and PalletScan.

class PalletScanHelper {

    struct MovementScan: Codable {
        var locationId: String?
        var palletId: String?
        var palletType: String?
        var timestamp: String?

        enum CodingKeys: String, CodingKey {
            case locationId = "LocationId"
            case palletId = "PalletId"
            case palletType = "PalletType"
            case timestamp = "TimeStamp"
        }

        enum MovementScanKeys: String, CodingKey {
            case locationId = "locationId"
            case palletId = "palletId"
            case palletType = "palletType"
            case timestamp = "timestamp"
        }

        init(locationId: String, palletId: String, palletType: String, timestammp: String ){
            self.locationId = locationId
            self.palletId = palletId
            self.palletType = palletType
            self.timestamp = timestammp
        }

        init(){
            self.locationId = nil
            self.palletId = nil
            self.palletType = nil
            self.timestamp = nil
        }

        //overide required for JSon to work
        init(from decoder: Decoder) throws {
            let values = try decoder.container(keyedBy: MovementScanKeys.self)
            let locationId: String =  try values.decode(String.self, forKey: .locationId)
            let palletId: String =  try values.decode(String.self, forKey: .palletId)
            let palletType: String =  try values.decode(String.self, forKey: .palletType)
            let timestamp: String =  try values.decode(String.self, forKey: .timestamp)

            self.init(locationId: locationId, palletId: palletId, palletType: palletType, timestammp: timestamp)
        }

        func encode(to encoder: Encoder) throws {
            var container = encoder.container(keyedBy: MovementScanKeys.self)

            try container.encode(locationId, forKey: .locationId)
            try container.encode(palletId, forKey: .palletId)
            try container.encode(palletType, forKey: .palletType)
            try container.encode(timestamp, forKey: .timestamp)

            print("Encoded container: ", container)
        }

    }

    struct PalletScan: Codable {
        var deliveryId: String?
        var userId: String?
        var timestamp: String?
        var tempPalletNr: String?
        var tempLocation: String?
        var tempPalletType: String?
        var pallets: [MovementScan] = [MovementScan]()

        //coding keys requried for translation API -> struct -> CoreData and CoreData -> struct -> API
        enum CodingKeys: String, CodingKey {
            case deliveryId = "TOID"
            case userId = "UserId"
            case timestamp = "TimeStamp"
        }

        init(deliveryId: String, userId: String, timestamp: String, movementScans: [MovementScan]) {
            self.deliveryId = deliveryId
            self.userId = userId
            self.timestamp = timestamp
            for item in movementScans {
                self.pallets.append(item)
                print(item)
            }
        }

        init(deliveryId: String, userId: String, timestamp: String, tempPalletType: String, tempLocation: String, tempPalletNr: String) {
            self.deliveryId = deliveryId
            self.userId = userId
            self.timestamp = timestamp
            self.tempPalletType = tempPalletType
            self.tempLocation = tempLocation
            self.tempPalletNr = tempPalletNr
        }

        init() {
            self.deliveryId = nil
            self.userId = nil
            self.timestamp = nil
            self.pallets = []
        }
}

MovementScan is nested within pallet scan. Encoding of MovementScan works fine, getting proper JSON string. However when wants to encode Pallet scan not getting nested MovementScan objects encoded into JSON.

 do {
                //req.httpBody = try encoder.encode(self)
                let jsonData = try encoder.encode(self)
                let jsonString = String(data: jsonData, encoding: .utf8)
                print (jsonString)
            } catch {
                //TODO:error handling
            }

encoding only me only main PalletScan items while MovementScan is not encoded at all. Should I place MovementScan encoder within parent PalletScan struct?

Upvotes: 1

Views: 285

Answers (1)

Au Ris
Au Ris

Reputation: 4659

Your PalletScan is missing some coding keys, even if you're not mapping all keys, you need to list them all:

     enum CodingKeys: String, CodingKey {
        case tempPalletNr, tempLocation, tempPalletType, pallets
        case deliveryId = "TOID"
        case userId = "UserId"
        case timestamp = "TimeStamp"
    }

P.s. your code example misses a closing brace for PalletScan struct.

Upvotes: 1

Related Questions