tristanhimmelman / ObjectMapper

Simple JSON Object mapping written in Swift
MIT License
9.16k stars 1.03k forks source link

Can't map array with generic method #1051

Closed ghost closed 5 years ago

ghost commented 5 years ago

i want to map my response for api calls. I have written a generic method to handle all api call. Below is method

 func post<T: Mappable>(obj: T.Type, endPoint:String ,params:[String:Any], success : @escaping (T) -> Void, failure : @escaping (String) -> Void){
        Alamofire.request(baseUrl+endPoint,method: .post, parameters:params).responseObject { (response:DataResponse<BaseResponse<T>>) in
            switch response.result {
            case .success(let response):
            .....
            case .failure(let error):
            .....
            }
        }
    }

BaseResponse:

struct BaseResponse<T:Mappable>:Mappable{
    var status:Int?
    var message:String?
    var data:T?
    mutating func mapping(map: Map) {
        status  <- map["status"]
        message <- map["message"]
        data    <- map["data"]
    }
    init?(map: Map) {}
}

Now usually i am using above method like this

 Api.shared.post(obj: TokenResponse.self, endPoint: EndPoints.availability.rawValue, params: [Keys.token:BaseVC.authToken, Keys.availability:NSNumber(value: isAvailable)], success: successBlock)

This works fine when response json have keys but now i have to handle this json which dont have keys inside 'data'

This is json i wanna parse:

{
    "status": 200,
    "message": "Patient List",

    "data": [
        {
            "user_info": {
                "name": "abx",
                "email": "abx@abx.com.pk",
                "phone": "4087082831"
            },
            "patient_info": {
                "p_name": "abx",
                "p_email": "abx@abx.com.pk",
                "p_phone": "4087082831"
            }
        },
        {

            "user_info": {
                "name": "abx",
                "email": "abx@abx.com.pk",
                "phone": "4087082831"
            },
            "patient_info": {
                "p_name": "abx",
                "p_email": "abx@abx.com.pk",
                "p_phone": "4087082831"
            }
        }
    ]
}

I'm having trouble creating mappable class for above json since it don't have keys inside data. Please help! thanks!

RomanPodymov commented 5 years ago

Hello @asadhyt Probably you should declare var data as [T]?.

PH9 commented 5 years ago

I think this issue is duplicated with #1043

zackdotcomputer commented 5 years ago

@PH9 - I'm pretty sure this issue is separate since it both doesn't involve Swift 5 and because I am still experiencing it after upgrading to ObjectMapper 3.5.x.

This issue as I understand it here is that ObjectMapper understands a slew of types that don't conform to the Mappable protocol - both "Nesting" objects like arrays and dictionaries and "Primative" values like strings and booleans. However, because they don't conform to the Mappable protocol, @asadhyt can't pass them as the generic argument to his class and, even if he could, the Mapper generic format doesn't successfully unwrap objects that aren't Mappable. I haven't dug into the code yet, but I think the solution is either going to be to make those types all Mappable or to correct the Mapper so that it can understand either Mappable types or these raw mappable types.

zackdotcomputer commented 5 years ago

For now, @asadhyt, I'm working around this in my app in the following way:

  1. My BaseResponse class is now just a protocol that defines an expectation of the fields a response will have. In your case, status, message, and data.
  2. I made a ResponseWithObject<T: Mappable> and ResponseWithArrayOfObject<T: Mappable> class, each of which looks like your class and conform to BaseResponse, except the Array variant follows @RomanPodymov's suggestion of declaring data to be of type [T]?
  3. I added a second generic to my post method of Response: BaseResponse that declares which response type is expected.
ghost commented 5 years ago

Thanks everyone.

steve7688 commented 3 years ago

@zackdotcomputer thanks for sharing your idea.I noticed that this PR is closed at several years ago.But Im a new swifter.Did you find out an universal way or a different way to resolve this problem now?Thank you

zackdotcomputer commented 3 years ago

@steve7688 I wound up moving away from this package towards using Decodable

steve7688 commented 3 years ago

wow that's great.maybe I should learn how to integrate Decodable in my project