Lokesh Chowdary
Lokesh Chowdary

Reputation: 736

Swift: How to convert a struct as dictionary along with hierarchical of keys

I want to convert a CollegeRequest type to a dictionary or data to send it to a server while requesting POST-API.

Here is my CollegeRequest type:

struct CollegeRequest: Codable {
    struct Student: Codable {
        var id: Int
        var name: String
    }
    var student: Student
    var date: Date
}

Once converted (along with the hierarchical keys), it should be like this:

{
  "student.id": 3,
  "student.name": "Raj",
  "date": "2019-10-31T13:59:00+00:00"
}

How can I achieve this ?

Upvotes: 0

Views: 201

Answers (1)

Blazej SLEBODA
Blazej SLEBODA

Reputation: 9925

Use Encodable protocol to encode your cutom struct type CollegeRequest. Your structure needs a manual encoding

If the structure of your Swift type differs from the structure of its encoded form, you can provide a custom implementation of Encodable and Decodable to define your own encoding and decoding logic. source

To encode the CollegeRequest to Data type, use JSONEncoder. An object that encodes instances of a data type as JSON objects.

Concerning the date stored property you you have to use JSONEncoder.DateEncodingStrategy.formatted(_:), the strategy that defers formatting settings to a supplied date formatter.

struct CollegeRequest: Codable {
    struct Student: Codable {
        var id: Int
        var name: String
    }
    var student: Student
    var date: Date

    enum CodingKeys: String, CodingKey {
        case studentId = "student.id"
        case studentName = "student.name"
        case date
    }

    func encode(to encoder: Encoder) throws {

        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(student.id, forKey: .studentId)
        try container.encode(student.name, forKey: .studentName)
        try container.encode(date, forKey: .date)
    }

    init(student: CollegeRequest.Student, date: Date) {
        self.student = student
        self.date = date
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        let studentId = try values.decode(Int.self, forKey: .studentId)
        let studentName = try values.decode(String.self, forKey: .studentName)
        student = Student(id: studentId, name: studentName)
        date = try values.decode(Date.self, forKey: .date)
    }

}

Usage

let request = CollegeRequest(student: CollegeRequest.Student(id: 1, name: "John"), date: Date())
let jsonEncoder = JSONEncoder()
let df = { let df = DateFormatter(); df.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"; return df }() as DateFormatter
jsonEncoder.dateEncodingStrategy = .formatted(df)
let a: Data? = try? jsonEncoder.encode(request)

Upvotes: 1

Related Questions