Md. Ibrahim Hassan
Md. Ibrahim Hassan

Reputation: 5477

How to add Nested arrays to my model class

I get the below response from the API. I need to model the response into classes in swift 3. The Api Response in JSON is as below:

{
  "data": [
    {
      "CategoryName": "אהבה",
      "CategoryID": "61",
      "CategoryDate": "2016-08-26 02:11:43",
      "CategoryImage": "love.png",
      "SubCategoryArray": [
        {
          "SubCategoryName": "אהבה",
          "SubCategoryRefID": "61",
          "SubCategoryID": "115",
          "SubCategoryDate": "2016-08-29 09:25:56",
          "TextArray": [
            {
              "TextID": "103",
              "Text": "<p dir=\"rtl\"><span style=\"font-size:48px\"><strong>אוהב</strong> אותך כל כך</span></p>\r\n"
            },

How can I model the subCategory and TextArray subclasses.

I am using SwiftyJSON to populate my model class

My model classes are as shown below;

class Menu
{
    var CategoryName: String?
    var CategoryID: String?
    var CategoryDate: String?
    var CategoryImage: String?
    var SubCategoryArray: [SubCategoryArray]?

    init(CategoryName: String?, CategoryID: String?, CategoryDate: String?, CategoryImage: String?, SubCategoryArray: [SubCategoryArray]?) {
        self.CategoryName = CategoryName
        self.CategoryID = CategoryID
        self.CategoryDate = CategoryDate
        self.CategoryImage = CategoryImage
        self.SubCategoryArray = SubCategoryArray
    }
}


class SubCategoryArray
{
    var SubCategoryName: String?
    var SubCategoryRefID: String?
    var SubCategoryID: String?
    var SubCategoryDate: String?
    var TextArray : [TextArray]?
    init(SubCategoryName: String?, SubCategoryRefID: String?, SubCategoryID: String?, SubCategoryDate: String?, TextArray: [TextArray]?) {
        self.SubCategoryName = SubCategoryName
        self.SubCategoryRefID = SubCategoryRefID
        self.SubCategoryID = SubCategoryID
        self.SubCategoryDate = SubCategoryDate
        self.TextArray = TextArray
    }
}


class TextArray
{
    var TextID: String?
    var Text: String?

    init (TextID:String? , Text: String? )
    {
        self.TextID = TextID
        self.Text = Text
    }
}

I am storing it as

if let json = try? JSON(result){
var menus = [Menu]()                    
for (_, content) in json["data"] {
let menu = Menu(CategoryName: (content["CategoryName"].string),
 CategoryID: content["CategoryID"].string,
 CategoryDate: content["CategoryDate"].string,
 CategoryImage: content["CategoryImage"],
 SubCategoryArray: content["SubCategoryArray"].string)
 menus.append(menu)
 }

The only issue is how to do it for the SubCategory class and TextArray class.

Upvotes: 1

Views: 1102

Answers (1)

dirtydanee
dirtydanee

Reputation: 6151

First of all, i would recommend to lowercase the variable names.

Also, i would rename TextArray class to Text, and SubCategoryArray class to SubCategory, because they are not arrays, and the name can be very misleading.

At last, lets initialise subCategoryArray and textArray as an empty array of SubCategory and Text, instead of being optional. This way, whenever you use it in the future, you do not have to run nil check on it, just check if isEmpty.

What you need to do, is just to iterate on the incoming object, and create your arrays. Please, take a look on the code below.

class Menu {
    var categoryName: String?
    var categoryID: String?
    var categoryDate: String?
    var categoryImage: String?
    var subCategoryArray = [SubCategory]()

    init(categoryName: String?, categoryID: String?, categoryDate: String?, categoryImage: String?, subCategoryArray: [Any]?) {
        self.categoryName = categoryName
        self.categoryID = categoryID
        self.categoryDate = categoryDate
        self.categoryImage = categoryImage

        // lets check if SubCategoryArray is not nil
        if let subCategoryArray = subCategoryArray as? [[String: AnyObject]] {
            // lets iterate on the raw data
            subCategoryArray.forEach({ (subCategoryCandidate) in
                // Create category
                let subcategory = SubCategory(subCategoryName: subCategoryCandidate["SubCategoryName"] as? String, 
                    subCategoryRefID: subCategoryCandidate["SubCategoryRefID"] as? String, 
                    subCategoryID: subCategoryCandidate["SubCategoryID"] as? String,
                    subCategoryDate: subCategoryCandidate["SubCategoryDate"] as? String, 
                    textArray: subCategoryCandidate["TextArray"] as? [[String: AnyObject]])
                // Append to our array
                self.subCategoryArray.append(subcategory)
            })
        }
    }
}

// lets rename this class only to SubCategory, because this is not an array at all
class SubCategory {
    var subCategoryName: String?
    var subCategoryRefID: String?
    var subCategoryID: String?
    var subCategoryDate: String?
    var textArray = [Text]()
    init(subCategoryName: String?, subCategoryRefID: String?, subCategoryID: String?, subCategoryDate: String?, textArray: [[String: AnyObject]]?) {
        self.subCategoryName = subCategoryName
        self.subCategoryRefID = subCategoryRefID
        self.subCategoryID = subCategoryID
        self.subCategoryDate = subCategoryDate

        if let textArray = textArray {
            textArray.forEach({ (textArrayCandidate) in
                let text = Text(textID: textArrayCandidate["TextID"] as? String, text: textArrayCandidate["Text"] as? String)
                self.textArray.append(text)
            })
        }
    }
}

// Rename this to Text, because this is also not an array
class Text {
    var textID: String?
    var text: String?

    init(textID:String? , text: String? ) {
        self.textID = textID
        self.text = text
    }
}

USAGE

let url = URL(string: "YOUR-URL")
let request = URLRequest(url: url!)
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)

let task = session.dataTask(with: request, completionHandler: {(data, response, error) in
    if let data = data, let json = try? JSON(data) {

        var menus = [Menu]()                    
        for (_, content) in json["data"] {
            let menu = Menu(categoryName: (content["CategoryName"].string),
                            categoryID: content["CategoryID"].string,
                            categoryDate: content["CategoryDate"].string,
                            categoryImage: content["CategoryImage"].string,
                            subCategoryArray: content["SubCategoryArray"].arrayObject)
            menus.append(menu)
        }

        print(menus) // prints 6 items for me
    }
});
task.resume()        

}

Upvotes: 3

Related Questions