Search code examples
iosiphoneswiftobjectobjectmapper

How to create a wrapper function for "ObjectMapper" library in swift


I am using ObjectMapper library to map my JSON object to Swift object. The traditional method of library is working fine for me like below code.

tmpArray1 = Mapper<UserModel>().mapArray(JSONArray: result1)
tmpArray2 = Mapper<CompanyModel>().mapArray(JSONArray: result2)

Now, I want to create a generic method to return dynamic object according to argument which i pass in that function. I want somewhat like below.

tmpArray1 = WrapperClass.shared.getModelObject(objType: UserModel, data: Any)
tmpArray2 = WrapperClass.shared.getModelObject(objType: CompanyModel, data: Any)

Here is my WrapperClass.swift class code:

open class WrapperClass: NSObject {

    static let shared = WrapperClass()

    open func getModelObject(objType: Mappable, data: Any) -> Any? {
        // Need Help Here
        return <dynamic object>
    }
}

I don't know my approach is 100% right but i want somewhat like whatever object type i pass in the argument of the function i want same object type in return with mapped with ObjectMapper object. I am using Swift 4.0 version.

You can find the ObjectMapper here.

Update: I have tried below thing but it will not work, show an error

func getModelObject<T: Mappable>(modelType: T.Type, data: Any) -> [T]? {

    if data is Array<Any> {
       return Mapper<modelType>().mapArray(JSONArray: data as! [[String: Any]])
       //ERROR: Use of undeclared type 'modelType'
    }
    return nil
}

Solution

  • You can achieve that by combination of generics and Type. It allows you to instantiate the mappable object with generic T (no Mapper<...> here):

    func getModelObject<T: Mappable>(objType: T.Type, data: Any) -> T? {
        if let data = data as? [String: Any] {
            return T(JSON: data)
        } else if let data = data as? String {
            return T(JSONString: data)
        }
        return nil
    }
    

    Example of usage:

    class User: Mappable {
        var name: String!
        var age: Int!
    
        required init?(map: Map) {}
    
        func mapping(map: Map) {
            name <- map["name"]
            age <- map["age"]
        }
    }
    
    let json = "{\"name\":\"Bob\",\"age\":100}"
    if let user = WrapperClass.shared.getModelObject(objType: User.self, data: json) {
        print(user.name, user.age)
    }
    

    Answer with Mapper<...>:

    func getModelObject<T: Mappable>(data: Any) -> [T]? {
        if let data = data as? [[String: Any]] {
            return Mapper<T>().mapArray(JSONArray: data)
        }
        return nil
    }