JSON response to populate multiple Sections and Rows in tableView

时间:2018-02-03 09:07:50

标签: json swift

I have the following JSON response:

{
"IT":[
    {
    "REPORT_NAME_EN":"Maecenas Eu Arcu",
    "REPORT_DESCRIPTION_EN":"Numquam optio, doloribus, adipisci recusandae enim."
    }
],
"Marketing":[
    {
    "REPORT_NAME_EN":"Brain Capacity",
    "REPORT_DESCRIPTION_EN":"Lorem ipsum dolor sit amet, consectetur adipisicing elit."
    },
    {
    "REPORT_NAME_EN":"Lorem Ipsum Dolor",
    "REPORT_DESCRIPTION_EN":"Vitae harum atque possimus distinctio dolores nostrum optio."
    }
],
"Network":[
    {
    "REPORT_NAME_EN":"Quisque Interdum",
    "REPORT_DESCRIPTION_EN":"Quod, natus, nihil. Repellat dolore, doloremque laborum exercitationem consectetur."
    }
]
}

I would like to have it displayed as follow in a tableview with multiple sections (and rows):

Section 0: "IT"
Row 0: "REPORT_NAME_EN" & "REPORT_DESCRIPTION_EN"

Section 1: "Marketing"
Row 0: "REPORT_NAME_EN" & "REPORT_DESCRIPTION_EN"
Row 1: "REPORT_NAME_EN" & "REPORT_DESCRIPTION_EN"

Section 2: "Network"
Row 0: "REPORT_NAME_EN" & "REPORT_DESCRIPTION_EN"

I usually append my JSON results to an NSArray but it's the first time I use and receive a multidimensional JSON and I'm having trouble to append:

var arrJSON = [[String:Any]]()
do {
    if let data = data,
        let json = try JSONSerialization.jsonObject(with: data) as? [String: Any]{
        self.arrJSON = [json] as [[String:Any]]
    }
}

When I do a arrJSON.count it gives me a result of 1 but it should be 3.

Would I be better off to bring two JSON responses (one to populate my sections and the other for my rows)?

2 个答案:

答案 0 :(得分:2)

Rather than using "primitive" collection types it's highly recommended to use custom structs for the reports and the sections.

The JSON is decoded with Decodable and mapped to an array of Section

struct Section {
    let name : String
    let reports : [Report]
}

struct Report : Decodable {
    let name : String
    let description : String

     private enum CodingKeys : String, CodingKey {
        case name = "REPORT_NAME_EN"
        case description = "REPORT_DESCRIPTION_EN"
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        name = try container.decode(String.self, forKey: .name)
        description = try container.decode(String.self, forKey: .description)
    }
}

let jsonString = """
{
    "IT":        [{"REPORT_NAME_EN":"Maecenas Eu Arcu",
                   "REPORT_DESCRIPTION_EN":"Numquam optio, doloribus, adipisci recusandae enim."}],
    "Marketing": [{"REPORT_NAME_EN":"Brain Capacity",
                   "REPORT_DESCRIPTION_EN":"Lorem ipsum dolor sit amet, consectetur adipisicing elit."},
                  {"REPORT_NAME_EN":"Lorem Ipsum Dolor",
                   "REPORT_DESCRIPTION_EN":"Vitae harum atque possimus distinctio dolores nostrum optio."}],
    "Network":   [{"REPORT_NAME_EN":"Quisque Interdum",
                   "REPORT_DESCRIPTION_EN":"Quod, natus, nihil. Repellat dolore, doloremque laborum exercitationem consectetur."}]}
"""

do {
    let data = Data(jsonString.utf8)
    let result = try JSONDecoder().decode([String:[Report]].self, from: data)
    let sections = result.map{ (key, value) -> Section in
        Section(name:key, reports:value)
    }
    print(sections)

} catch {
    print("error: ", error)
}

Declare the data source array

var sections = [Section]()

In numberOfSections return

sections.count

In numberOfRowsInSection return

sections[section].reports.count

In cellforRow get a report

let section = sections[indexPath.section]
let report = section.reports[indexPath.row]

In titleForHeaderInSection return

sections[section].name

答案 1 :(得分:0)

just try updating your code to this

var arrJSON = [[String:Any]]()
do {
if let data = data,
        let json = try JSONSerialization.jsonObject(with: data, options: []) as? [[String: Any]] {
        self.arrJSON = json 
    }
}