1

I'm writing in Swift 4, using viper structure and ObjectMapper to map my JSON response to my models.

I'm trying to map this rather complex JSON response with dynamic keys and am hoping to get some feedback on what I'm doing wrong.

Document is uploaded in whole month is return with month name as key and its all document list with value. My response is like this json:

{  
    "results": {
        "2019-08": [
            {
                "id": 2,
                "user_id": 7,
                "document": "1566282328atlassian-git-cheatsheet1.pdf",
                "name": "atoz",
                "order": 0,
                "is_edit": 0,
                "edit_json": "",
                "created_at": "2019-08-20 06:25:28",
                "updated_at": "2019-08-20 06:25:28",
                "date": "2019-08",
                "url": "http://35.154.206.145/storage/pdf/1566282328atlassian-git-cheatsheet1.pdf"
            },
        { ….}                
        ],
  "2019-07": [
            {
                "id": 2,
                "user_id": 7,
                "document": "1566282328atlassian-git-cheatsheet1.pdf",
                "name": "atoz",
                "order": 0,
                "is_edit": 0,
                "edit_json": "",
                "created_at": "2019-08-20 06:25:28",
                "updated_at": "2019-08-20 06:25:28",
                "date": "2019-08",
                "url": "http://35.154.206.145/storage/pdf/1566282328atlassian-git-cheatsheet1.pdf"
            },
       { ….}   
        ]
    }
}

My model class is like this to fetch data in mapper model class

import ObjectMapper

struct GroupResponse: Mappable {

    init?(map: Map) {}

    var results: [String: DocumentObject]?

    mutating func mapping(map: Map) {
        results   <- map["results"]
    }
}

class DocumentObject: Mappable{

    internal var months: [String: [DocumentListObject]]?

    required init?(map: Map) {}

    func mapping(map: Map) {
        for (monthKey, monthValue) in map.JSON as! [String: [String: Any]] {
            let month = DocumentListObject()
            months?[monthKey] = [month]
        }
    }
}

class DocumentListObject {

     var id:Int?
     var user_id:Int?
     var document:String?
     var name:String?
     var order:Int?
     var is_edit:Bool?
     var edit_json:String?
     var date:String?
     var url:String?
}

what is wrong in this, I get nil and crash when fatch this in api response

if let json = data as AnyObject? {
                let arrayResponse = json as! NSDictionary

                let arrayObject = Mapper<GroupResponse>().mapDictionary(JSON: arrayResponse as! [String : [String : Any]]) // I got crash here
                print(arrayObject)

1 Answer 1

1

No need for DocumentObject. try this,

struct GroupResponse: Mappable {

    init?(map: Map) {}

    var results: [String: [DocumentListObject]]?

    mutating func mapping(map: Map) {
        results   <- map["results"]
    }
}

Also, you forget to make DocumentListObject conforming to Mappable. Please update it as below,

class DocumentListObject: Mappable {

    var id:Int?
    var user_id:Int?
    var document:String?
    var name:String?
    var order:Int?
    var is_edit:Bool?
    var edit_json:String?
    var date:String?
    var url:String?

    required init?(map: Map) {}

    func mapping(map: Map) {
        id   <- map["id"]
        user_id   <- map["user_id"]
        document   <- map["document"]
        name   <- map["name"]
        order   <- map["order"]
        is_edit   <- map["is_edit"]
        edit_json   <- map["edit_json"]
        date   <- map["date"]
        url   <- map["url"]
    }
}

Usage:

        let data = """
{
    "results": {
        "2019-08": [
            {
                "id": 2,
                "user_id": 7,
                "document": "1566282328atlassian-git-cheatsheet1.pdf",
                "name": "atoz",
                "order": 0,
                "is_edit": 0,
                "edit_json": "",
                "created_at": "2019-08-20 06:25:28",
                "updated_at": "2019-08-20 06:25:28",
                "date": "2019-08"
            }
          ]
       }
}
"""

        if let r = GroupResponse.init(JSONString: data), let result = r.results {
            for (key, value) in result {
                print("Key: \(key)" )
                print("DocumentName: \(value.first!.document!)")
            }
        }
// prints
Key: 2019-08
DocumentName: 1566282328atlassian-git-cheatsheet1.pdf

When you have JSON from the response, use below example to parse the GroupResponse.

let json = your JSON (of type [String: Any]) object retrieved from the API
if let r = GroupResponse.init(JSON: json), let result = r.results {
    for (key, value) in result {
        print("Key: \(key)" )
        print("DocumentName: \(value.first!.document!)")
    }
}
Sign up to request clarification or add additional context in comments.

5 Comments

@riddhi I update the answer with another fix. Please try.
can not define GroupResponse object with JSONString. what is your syntax?
If you have JSON, the use that as if let r = GroupResponse.init(JSON: yourJSON), let result = r.results {
If you are using ObjectMapper, you can reduce a lot of boilerplate code by using BetterMappable (github.com/PhonePe/BetterMappable) which is written over ObjectMapper using PropertyWrappers. You need to be on Swift 5.1 to use it.
@Srikanth, Looks promising. Hope you take care of future compatibility.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.