Vlado Svitok
Vlado Svitok

Reputation: 41

Swift - Serialize object containing array of objects and send with alamofire

i need to send post request with class as parameter using Alamofire. My class contains array of other class and I'm stuck because of that.

class CreateRecordData{
    var RecordDate: String?
    var RecordType: String?
    var SubType: String?
    var Name: String?
    var MovementRecords: [RecordMovementData]?
    var MeasurementId: Int?
    var SensorType: String?
}


class RecordMovementData{
    var FrameRate: Int?
    var JointType: String?
    var Samples: [MovementSampleData]?
    var RecordId: Int?
}



class MovementSampleData {
    var Id: Int?
    var TimeStamp: Int64?
    var X: Float?
    var Y: Float?
    var Z: Float?
}

I'm kinda new in swift and couldn't get this done in some time.

What's the way to approach this.

I need CreateRecordData class to send as parameter using alamofire.

Thanks

classes after adding Encodable

class CreateRecordData: Encodable{
    var RecordDate: String?
    var RecordType: String?
    var SubType: String?
    var Name: String?
    var AudioRecords: [AudioData]?
    var MovementRecords: [RecordMovementData]?
    var MeasurementId: Int?
    var SensorType: String?

    enum CodingKeys: String, CodingKey {
        case RecordDate
        case RecordType
        case SubType
        case Name
        case AudioRecords
        case MovementRecords
        case MeasurementId
        case SensorType
    }
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(RecordDate, forKey: .RecordDate)
        try container.encode(RecordType, forKey: .RecordType)
        try container.encode(SubType, forKey: .SubType)
        try container.encode(Name, forKey: .Name)
        try container.encode(AudioRecords, forKey: .AudioRecords)
        try container.encode(MovementRecords, forKey: .MovementRecords)
        try container.encode(MeasurementId, forKey: .MeasurementId)
        try container.encode(SensorType, forKey: .SensorType)
    }
}

class RecordMovementData: Encodable{
    var FrameRate: Int?
    var JointType: String?
    var Samples: [MovementSampleData]?
    var RecordId: Int?

    enum CodingKeys: String, CodingKey{
        case FrameRate
        case JointType
        case Samples
        case RecordId
    }
    func encode(to encoder: Encoder) throws{
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(FrameRate, forKey: .FrameRate)
        try container.encode(JointType, forKey: .JointType)
        try container.encode(Samples, forKey: .Samples)
        try container.encode(RecordId, forKey: .RecordId)
    }
}


class MovementSampleData: Encodable {
    var Id: Int?
    var TimeStamp: Int64?
    var X: Float?
    var Y: Float?
    var Z: Float?

    enum CodingKeys: CodingKey{
        case Id
        case TimeStamp
        case X
        case Y
        case Z
    }
    func encode(to encoder: Encoder) throws{
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(Id, forKey: .Id)
        try container.encode(TimeStamp, forKey: .TimeStamp)
        try container.encode(X, forKey: .X)
        try container.encode(Y, forKey: .Y)
        try container.encode(Z, forKey: .Z)
    }
}

One more thing to mention. a don't directly use CreateRecordData as parameter. I create Dictionary with data of that class like this:

let recordParams: [String:Any] = [
            "RecordDate": recordData.RecordDate!,
            "RecordType": recordData.RecordType!,
            "SubType": recordData.SubType!,
            "Name": recordData.Name!,
            "AudioRecords": "",
            "MovementRecords": recordData.MovementRecords!,
            "MeasurementId": "\(recordData.MeasurementId!)",
            "SensorType": recordData.SensorType!
        ]

        AF.request("https://repac-fe-v1-webapp.azurewebsites.net/api/record",method: .post, parameters: recordParams, encoding: JSONEncoding.default, headers: header).responseJSON { response in

        }

There might be something wrong with that as well

Upvotes: 2

Views: 480

Answers (1)

gcharita
gcharita

Reputation: 8327

Since the keys in your JSON are the same as the names of your model properties you can omit the CodingKeys enums from your model classes. Also, since you are not doing something custom in encoding you can completely omit the implementation of the encode(to:) function:

class AudioData: Encodable {
    // This class is missing from the posted code
}

class CreateRecordData: Encodable {
    var RecordDate: String?
    var RecordType: String?
    var SubType: String?
    var Name: String?
    var AudioRecords: [AudioData]?
    var MovementRecords: [RecordMovementData]?
    var MeasurementId: Int?
    var SensorType: String?
}

class RecordMovementData: Encodable {
    var FrameRate: Int?
    var JointType: String?
    var Samples: [MovementSampleData]?
    var RecordId: Int?
}

class MovementSampleData: Encodable {
    var Id: Int?
    var TimeStamp: Int64?
    var X: Float?
    var Y: Float?
    var Z: Float?
}

Making a post request with an Encodable object as parameters is simpler than you thought. You just call the request method that takes an encoder not an encoding as a parameter:

let recordParams = CreateRecordData() // Set the class values here

AF.request(
    "https://repac-fe-v1-webapp.azurewebsites.net/api/record",
    method: .post,
    parameters: recordParams,
    encoder: JSONParameterEncoder.default,
    headers: header
).responseJSON { response in
    
}

Upvotes: 1

Related Questions