tristanhimmelman / ObjectMapper

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

Does it work with swift2 and iOS 9? #203

Closed athalay closed 9 years ago

athalay commented 9 years ago

I'm willing to use this library with iOS9 and swift through cocoapods.

Unfortunately deserialization json to object always give null result:

//DTO class:

import ObjectMapper

class ResponseResult : Mappable
{
    var IsSuccessful: Bool?;
    var ErrorMessage: String?;
    var SuccessMessage: String?;

        required init?(_ map: Map){

            }

 func mapping(map: Map) {

        IsSuccessful <- map["IsSuccessful"]
ErrorMessage <- map["ErrorMessage"]
SuccessMessage <- map["SuccessMessage"]

    }
}

// USAGE:

Alamofire.request(.POST, "http://192.168.0.12:57336/Account/LogOnMobile", parameters: loginParams)
            .responseString(completionHandler: { (request, response, json) -> Void in

                debugPrint(json.value);

                let user = Mapper<ResponseResult>().map(json.value)
                });
tristanhimmelman commented 9 years ago

Yes ObjectMapper works with swift 2.0 and iOS 9.

Can you post your JSON response? Otherwise its difficult to figure out what is going wrong.

athalay commented 9 years ago

Sorry, I'll paste my JSON here (more properties are coming back than which are present in my model class):

{"WodGeneratorSettings":{"FilterSettings":{"IsAllEquipmentSelected":false,"IgnoreRecentlyCompletedWorkouts":true,"IsOnlyFittingExercisesSelected":false,"SelectedTargetingOption":0,"IsAllExercisesSelected":true,"IsAllSchemesSelected":true,"IncludeCommunityWods":false,"IsAllDurationIntervalsSelected":true,"SelectedEquipment":[1,19,4],"Exercises":null,"Schemes":null,"DurationIntervals":null},"Exercises":null,"ExerciseEquipments":[{"EquipmentID":6,"ExerciseIDs":[97,76,122,130,125,128,129,124,127,2170,94,28,2166,104,23,135,12,2167,70,58]},{"EquipmentID":16,"ExerciseIDs":[101,33,140,159,34]},{"EquipmentID":1,"ExerciseIDs":[10,68,83,162,2,32,47,5,6,100,111,60,62,109,3,92,93,9,121,146,37,36,49,24,107,1,38,148,25,11,90]},{"EquipmentID":19,"ExerciseIDs":[41]},{"EquipmentID":17,"ExerciseIDs":[40,2169]},{"EquipmentID":2,"ExerciseIDs":[125,123,124,134,131,132,151,7,14,116,80,42,120,103]},{"EquipmentID":7,"ExerciseIDs":[128,127,117,118,45]},{"EquipmentID":9,"ExerciseIDs":[18,71,158]},{"EquipmentID":4,"ExerciseIDs":[54,55,79,110,51,57,56,63,108,50,133,105,48,1163,86,87,53,147,84]},{"EquipmentID":3,"ExerciseIDs":[86,87,146,147,4,89,8,46]},{"EquipmentID":18,"ExerciseIDs":[140,93,142,96,145]},{"EquipmentID":5,"ExerciseIDs":[2173,67,44,61,161]},{"EquipmentID":12,"ExerciseIDs":[2174,138,20,1164]},{"EquipmentID":13,"ExerciseIDs":[2175,154,1165]},{"EquipmentID":11,"ExerciseIDs":[92,1166,26,141]},{"EquipmentID":8,"ExerciseIDs":[19]},{"EquipmentID":10,"ExerciseIDs":[17]}],"ExerciseGroups":[{"ID":2,"Name":"Weightlifting","ExerciseIDs":[10,68,83,41,2,32,47,5,54,55,79,110,51,57,56,63,108,50,133,48,86,87,6,100,111,60,62,109,3,92,93,53,9,121,146,147,37,36,49,24,107,1,38,148,25,11,84,90]},{"ID":6,"Name":"Kettlebell","ExerciseIDs":[162,105,1163,2173,2174,2175,67,138,44,20,154,61,161,1164,1165]},{"ID":3,"Name":"Endurance","ExerciseIDs":[17,4]},{"ID":4,"Name":"Bodyweight","ExerciseIDs":[27,97,101,76,40,65,30,122,2169,130,125,128,2168,123,129,124,127,134,131,132,2170,94,28,95,33,140,155,21,2166,151,159,34,157,156,104,23,43,135,74,106,7,31,73,2176,12,13,14,116,80,42,120,19,22,142,2171,2172,117,118,45,2167,70,1166,98,58,103,85,46,114]},{"ID":5,"Name":"Coordination, Agility, Balance, Accuracy or Speed","ExerciseIDs":[150,18,113,115,89,71,8,158,26,96,141,145]},{"ID":1,"Name":"Other","ExerciseIDs":[]}],"WodSchemes":[{"ID":0,"Name":"Singlet"},{"ID":1,"Name":"Couplet"},{"ID":2,"Name":"Triplet"},{"ID":3,"Name":"Amrap"},{"ID":4,"Name":"Chipper"},{"ID":5,"Name":"Hybrid"}],"DurationIntervals":[{"Name":"\\u003c 10 mins","MinDurationInSecondsInclusive":-1,"MaxDurationInSecondsInclusive":600,"ID":1},{"Name":"10-20 mins","MinDurationInSecondsInclusive":600,"MaxDurationInSecondsInclusive":1200,"ID":2},{"Name":"20-30 mins","MinDurationInSecondsInclusive":1200,"MaxDurationInSecondsInclusive":1800,"ID":4},{"Name":"30+ mins","MinDurationInSecondsInclusive":1800,"MaxDurationInSecondsInclusive":-1,"ID":8}],"Wods":[],"TargetingOptions":[{"ID":0,"Name":"No targeting"},{"ID":1,"Name":"Endurance"},{"ID":2,"Name":"Strength"}]},"EquipmentSettings":[{"EquipmentId":11,"IsOwnedBySportsman":false,"EquipmentName":"10kg/22lbs medicine ball"},{"EquipmentId":18,"IsOwnedBySportsman":false,"EquipmentName":"5kg/11lbs medicine ball"},{"EquipmentId":3,"IsOwnedBySportsman":false,"EquipmentName":"Area to run"},{"EquipmentId":1,"IsOwnedBySportsman":true,"EquipmentName":"Barbell"},{"EquipmentId":19,"IsOwnedBySportsman":true,"EquipmentName":"Bench rack"},{"EquipmentId":4,"IsOwnedBySportsman":true,"EquipmentName":"Dumbbell"},{"EquipmentId":16,"IsOwnedBySportsman":false,"EquipmentName":"GHD machine"},{"EquipmentId":17,"IsOwnedBySportsman":false,"EquipmentName":"Jump box (60cm) "},{"EquipmentId":9,"IsOwnedBySportsman":false,"EquipmentName":"Jump rope"},{"EquipmentId":5,"IsOwnedBySportsman":false,"EquipmentName":"Kettlebell (16kg)"},{"EquipmentId":12,"IsOwnedBySportsman":false,"EquipmentName":"Kettlebell (24kg)"},{"EquipmentId":13,"IsOwnedBySportsman":false,"EquipmentName":"Kettlebell (32kg)"},{"EquipmentId":6,"IsOwnedBySportsman":false,"EquipmentName":"Pull-up bar"},{"EquipmentId":2,"IsOwnedBySportsman":false,"EquipmentName":"Rings"},{"EquipmentId":8,"IsOwnedBySportsman":false,"EquipmentName":"Rope to climb"},{"EquipmentId":10,"IsOwnedBySportsman":false,"EquipmentName":"Rower"},{"EquipmentId":7,"IsOwnedBySportsman":false,"EquipmentName":"Static dip bar"}],"SportsmanCoreSettings":{"ProfileUrl":"http://192.168.0.12:57336/Content/themes/gray/gfx/avatar_nophoto_150x150.png","FirstName":"110","LastName":"110"},"HealthLevelSettings":[{"BodyPartId":10,"Value":5,"Name":"Shoulder - Frontal press (Bench press push-ups, ring dips etc.)"},{"BodyPartId":9,"Value":10,"Name":"Shoulder - Overhead Pressing (Jerk, Push Press, Press etc.)"},{"BodyPartId":1,"Value":10,"Name":"Shoulder - Pulling movements (Pull ups, Clean, Snatch etc.)"},{"BodyPartId":7,"Value":10,"Name":"Acromioclavicular (AC) joint"},{"BodyPartId":11,"Value":10,"Name":"Elbow - Movements involving pressure on the joint"},{"BodyPartId":3,"Value":10,"Name":"Elbow - Movements involving twisting of the joint"},{"BodyPartId":13,"Value":10,"Name":"Wrist - Movements involving pressure on the joint"},{"BodyPartId":8,"Value":10,"Name":"Wrist - Movements involving twisting of the joint"},{"BodyPartId":6,"Value":10,"Name":"Spine"},{"BodyPartId":2,"Value":10,"Name":"Hip"},{"BodyPartId":12,"Value":10,"Name":"Knee - Movements involving pressure on the joint"},{"BodyPartId":4,"Value":10,"Name":"Knee - Movements involving twisting of the joint"},{"BodyPartId":5,"Value":10,"Name":"Ankle"}],"IsLoadUnitMetric":false,"IsSuccessful":true,"ErrorMessage":null,"NotAuthorizedRedirectTo":null,"RedirectTo":null,"SuccessMessage":null}
athalay commented 9 years ago

OK, got the problem.

Instead of

let user = Mapper<ResponseResult>().map(json.value)

, I have to use

let user = Mapper<ResponseResult>().map(json.value!)

(using "!" for json.value, so it's not an optional).

Is this a bug, or user-error? :)

tristanhimmelman commented 9 years ago

Ahh I just spotted your error.

ObjectMapper has different functions which you can use for mapping. Currently you are getting a string response from Alamofire. Since the response is a string you need to unwrap the optional due to the map function definition: public func map(JSONString: String) -> N?

However, you can also use Alamofire to return a JSON object (I recommend this approach). Given the JSON object you would use this function: public func map(JSON: AnyObject?) -> N?

If you choose to use my recommendation, your code would look like this:

Alamofire.request(.POST, "http://192.168.0.12:57336/Account/LogOnMobile", parameters: loginParams)
        .responseJSON { (request: NSURLRequest?, HTTPURLResponse: NSHTTPURLResponse?, result: Result<AnyObject>) -> Void in
        let user = Mapper<Forecast>().map(result.value)
}

Lastly, since you are using Alamofire and ObjectMapper together, I recommend you check out https://github.com/tristanhimmelman/AlamofireObjectMapper. It automatically converts your Alamofire responses into models using ObjectMapper.

athalay commented 9 years ago

Thanks a lot, Tristan, though maybe it could be a CR for consideration that inside you check whether the passed in string is optional or not, and if it is, then you handle this case inside. So others don't really have to mind what do they pass in.