swiftmodelobject-object-mapping

Json Object mapping Swift


I would like to do a Post request to a url however i just learnt of new concept in Swift called Object mapping. All the tutorial i have learnt how to map the Json object to swift structs or classes but non shows me how to use these objects once they are mapped.

How do i access these objects such that i use them when doing a post request.

Here is example Json:

{
  "country": "string",
  "dateOfBirth": "string",
  "email": "string",
  "gender": "string",
  "id": "string",
  "interaction": {
    "deviceOS": "string",
    "deviceType": "string",
    "interactionLocation": "string",
    "interactionType": "string",
    "timeStamp": "string"
  },
  "name": "string",
  "occupation": "string",
  "passportOrIDimage": "string",
  "phoneNumber": "string",
  "physicalAddress": "string",
  "salutation": "string",
  "surname": "string",
  "userlogin": {
    "accountNonExpired": true,
    "accountNonLocked": true,
    "credentialsNonExpired": true,
    "enabled": true,
    "password": "string",
    "roles": [
      {
        "roleName": "string"
      }
    ],
    "username": "string"
  }
}

Example Object mapping in swift 4 :

    struct Register: Codable {
    let country: String?
    let dateOfBirth: String?
    let email: String?
    let gender: String?
    let id: String?
    let interaction: Interaction?
    let name: String?
    let occupation: String?
    let passportOrIDimage: String?
    let phoneNumber: String?
    let physicalAddress: String?
    let salutation: String?
    let surname: String?
    let userlogin: Userlogin?

    enum CodingKeys: String, CodingKey {
        case country = "country"
        case dateOfBirth = "dateOfBirth"
        case email = "email"
        case gender = "gender"
        case id = "id"
        case interaction = "interaction"
        case name = "name"
        case occupation = "occupation"
        case passportOrIDimage = "passportOrIDimage"
        case phoneNumber = "phoneNumber"
        case physicalAddress = "physicalAddress"
        case salutation = "salutation"
        case surname = "surname"
        case userlogin = "userlogin"
    }
}

struct Interaction: Codable {
    let deviceOS: String?
    let deviceType: String?
    let interactionLocation: String?
    let interactionType: String?
    let timeStamp: String?

    enum CodingKeys: String, CodingKey {
        case deviceOS = "deviceOS"
        case deviceType = "deviceType"
        case interactionLocation = "interactionLocation"
        case interactionType = "interactionType"
        case timeStamp = "timeStamp"
    }
}

struct Userlogin: Codable {
    let accountNonExpired: Bool?
    let accountNonLocked: Bool?
    let credentialsNonExpired: Bool?
    let enabled: Bool?
    let password: String?
    let roles: [Role]?
    let username: String?

    enum CodingKeys: String, CodingKey {
        case accountNonExpired = "accountNonExpired"
        case accountNonLocked = "accountNonLocked"
        case credentialsNonExpired = "credentialsNonExpired"
        case enabled = "enabled"
        case password = "password"
        case roles = "roles"
        case username = "username"
    }
}

struct Role: Codable {
    let roleName: String?

    enum CodingKeys: String, CodingKey {
        case roleName = "roleName"
    }
}

// MARK: Convenience initializers

extension Register {
    init(data: Data) throws {
        self = try JSONDecoder().decode(Register.self, from: data)
    }

    init(_ json: String, using encoding: String.Encoding = .utf8) throws {
        guard let data = json.data(using: encoding) else {
            throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil)
        }
        try self.init(data: data)
    }

    init(fromURL url: URL) throws {
        try self.init(data: try Data(contentsOf: url))
    }

    func jsonData() throws -> Data {
        return try JSONEncoder().encode(self)
    }

    func jsonString(encoding: String.Encoding = .utf8) throws -> String? {
        return String(data: try self.jsonData(), encoding: encoding)
    }
}

extension Interaction {
    init(data: Data) throws {
        self = try JSONDecoder().decode(Interaction.self, from: data)
    }

    init(_ json: String, using encoding: String.Encoding = .utf8) throws {
        guard let data = json.data(using: encoding) else {
            throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil)
        }
        try self.init(data: data)
    }

    init(fromURL url: URL) throws {
        try self.init(data: try Data(contentsOf: url))
    }

    func jsonData() throws -> Data {
        return try JSONEncoder().encode(self)
    }

    func jsonString(encoding: String.Encoding = .utf8) throws -> String? {
        return String(data: try self.jsonData(), encoding: encoding)
    }
}

extension Userlogin {
    init(data: Data) throws {
        self = try JSONDecoder().decode(Userlogin.self, from: data)
    }

    init(_ json: String, using encoding: String.Encoding = .utf8) throws {
        guard let data = json.data(using: encoding) else {
            throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil)
        }
        try self.init(data: data)
    }

    init(fromURL url: URL) throws {
        try self.init(data: try Data(contentsOf: url))
    }

    func jsonData() throws -> Data {
        return try JSONEncoder().encode(self)
    }

    func jsonString(encoding: String.Encoding = .utf8) throws -> String? {
        return String(data: try self.jsonData(), encoding: encoding)
    }
}

extension Role {
    init(data: Data) throws {
        self = try JSONDecoder().decode(Role.self, from: data)
    }

    init(_ json: String, using encoding: String.Encoding = .utf8) throws {
        guard let data = json.data(using: encoding) else {
            throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil)
        }
        try self.init(data: data)
    }

    init(fromURL url: URL) throws {
        try self.init(data: try Data(contentsOf: url))
    }

    func jsonData() throws -> Data {
        return try JSONEncoder().encode(self)
    }

    func jsonString(encoding: String.Encoding = .utf8) throws -> String? {
        return String(data: try self.jsonData(), encoding: encoding)
    }
}

I would to put the data i want to post in the params dictionary this where i am not sure how to do so using object mapping.

My post request :

 var request = URLRequest(url: URL(string: "http://testURL")!)
request.httpMethod = "POST"
    request.httpBody = try? JSONSerialization.data(withJSONObject: params as Any, options: [])
request.addValue("application/json", forHTTPHeaderField: "Content-Type")

let session = URLSession.shared
let task = session.dataTask(with: request, completionHandler: { data, response, error -> Void in
    print(response!)
    do {
        let json = try JSONSerialization.jsonObject(with: data!) as! Dictionary<String, AnyObject>
        let alert = UIAlertController(title: "Response", message: "message", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: nil))
       print(json)
    } catch {
        print("error")
    }
})

task.resume()

}

Solution

  • if you observe in your struct

    func jsonData() throws -> Data {
        return try JSONEncoder().encode(self)
    }
    

    In your post request you can use like this

    request.httpBody = try?  objectOfCodableStruct.jsonData()
    

    Hope it is helpful