Ammo
Ammo

Reputation: 580

iOS objectmapper, mapping json with array

I have a simple question: how to convert such a json response to object with usage of Hearst-DD/ObjectMapper

{
   "errors": [
      {
         "code": "404",
         "message": "Wrong id"
      }
    ]
}

With swiftyJson i do

json["errors"][0]["code"]

but how to do it with objectmapper ? i tried this:

map["errors.code"]

and it does not work

EDIT: i did Error and ErrorResponse clasess like suggested, now:

//...
    let fullAddress = mainAddress + additionalAddr
    var parameters = ["email":email]

    manager.GET( fullAddress,
        parameters: parameters,
        success: { (operation: AFHTTPRequestOperation!,responseObject: AnyObject!) in
            //here is success, i got it done with user mapping
            callback(success: true)
        },
        failure: { (operation: AFHTTPRequestOperation!,error: NSError!) in

            let errorResponse = Mapper<ErrorResponse>().map(operation.responseString!)


            println(errorResponse!) //this prints: MyApp.ErrorResponse
            println(errorResponse?.errors!) //this prints: Optional([MyApp.Error]) 
            println(errorResponse?.errors![0]) //this prints:Optional(MyApp.Error)
            println(errorResponse?.errors![0].code) //<- this is nil :(
           // how to get the code mapped ?
            callback(success: false)
     })
}

Upvotes: 2

Views: 6701

Answers (2)

Marcio Duarte
Marcio Duarte

Reputation: 94

Your code doesn't work because the property errors is an array, and ObjectMapper try to convert it to an object.

For the JSON you have provided, the correct answer is as follow:

class Error: Mappable, Printable {
    var code: String?
    var message: String?

    init() {}

    class func newInstance() -> Mappable {
        return Error()
    }

    func mapping(map: Map) {
        self.code <- map["code"]
        self.message <- map["message"]
    }

    var description: String {
        get {
            return Mapper().toJSONString(self, prettyPrint: false)!
        }
    }
}

class ErrorResponse: Mappable, Printable {
    var errors: [Error]?

    init () {}

    class func newInstance() -> Mappable {
        return ErrorResponse()
    }

    func mapping(map: Map) {
        self.errors <- map["errors"]
    }

    var description: String {
        get {
            return Mapper().toJSONString(self, prettyPrint: false)!
        }
    }
}

Test:

    let json = "{\"errors\": [{\"code\": \"404\",\"message\": \"Wrong id\"}]}"

    let errorResponse = Mapper<ErrorResponse>().map(json)

    println("errorResponse: \(errorResponse?.description)")

    if let errors = errorResponse?.errors {
        println("errors: \(errors.description)")
        println("errors[0] \(errors[0])")
        println("errors[0].code \(errors[0].code)")
        println("errors.first!.message \(errors.first!.message)")
    }

Output:

errorResponse: Optional("{\"errors\":[{\"message\":\"Wrong id\",\"code\":\"404\"}]}")
errors: [{"message":"Wrong id","code":"404"}]
errors[0] {"message":"Wrong id","code":"404"}
errors[0].code Optional("404")
errors.first!.message Optional("Wrong id")

Upvotes: 4

ezcoding
ezcoding

Reputation: 2994

Should only pass the JSON-String and not a String you hand wrote to the map function.

From the README:

Once your class implements Mappable, the Mapper class handles everything else for you:

Convert a JSON string to a model object:

let user = Mapper<User>().map(JSONString)

So your scenario could be:

let error = Mapper<Error>().map(json)

Upvotes: 0

Related Questions