0

Given the following sample JSON

{
    "filters": [ 
      { "name" : "First Type",
        "types" : ["md", "b", "pb"]},
      { "name" : "Second Type",
        "types" : ["pt", "ft", "t"]},
      { "name" : "Third Type",
        "types" : ["c", "r", "s", "f"]
      }
    ],
    "jobs": [
        { "title":"f",
          "description" : "descrip text",
          "criteria":[ "md", "ft", "s" ],
          "img" : "www1"
        },
        { "title":"boa",
          "description" : "a description",
          "criteria":[ "b", "pb", "f", "ft" ],
          "img" : "www2"
        },
        { "title":"BK",
          "description" : "something here",
          "criteria":[ "md", "pt", "ft", "b", "s" ],
          "img" : "www3"
        }
    ]
 }

(Using Alamofire to create the response) let responseJSON : JSON = JSON(response.result.value!)

1) I am trying to convert these into two String arrays. One array: let filter = [String : [String]] and another array for the jobs. How do I do it? (aka give a man a fish) The following are some sample code snippets, but none are even close to working.

  let filterCategories = responseJSON["filters"].arrayValue.map({
          $0["name"].stringValue
  })

and

for (key,subJson):(String, JSON) in responseJSON["filters"] {
    let object : filterObject = filterObject(category: key, list: subJson.arrayValue.map({ $0.stringValue }))

  }

2) How do I learn how to use this properly? (aka teach a man to fish) I have been reading the documentation (https://github.com/SwiftyJSON/SwiftyJSON) but I'm struggling to understand it. I'm guessing the final answer will use .map, .stringValue, and .arrayValue. Ultimately though I'm trying to avoid lots of needless or unmanageable code.

Alex
  • 77
  • 1
  • 3
  • 11
  • If you're using Swift 4, then take a look at [Ultimate Guide to JSON Parsing with Swift 4](https://benscheirman.com/2017/06/swift-json/) – MadProgrammer Aug 10 '18 at 03:28

2 Answers2

1

Swift 4 provides JSON parsing support out of the box - maybe start within something like Ultimate Guide to JSON Parsing with Swift 4

Based on your available structure, I threw into a Playground and used...

// I was loading the JSON from a file within the Playground's Resource folder
// But basically, you want to end up with a reference to Data
let filePath = Bundle.main.path(forResource:"Source", ofType: "json")
let data = FileManager.default.contents(atPath: filePath!)

struct Filter: Codable {
    let name: String;
    let types: [String];
}

struct Job: Codable {
    let title: String;
    let description: String;
    let criteria: [String];
    let img: String;
}

struct Stuff: Codable {
    let filters: [Filter];
    let jobs: [Job];
}

let decoder = JSONDecoder();
let stuff = try! decoder.decode(Stuff.self, from: data!)

print("Filter:")
for filter in stuff.filters {
    print(filter.name)
    for type in filter.types {
        print(" - \(type)")
    }
}
print("Jobs:")
for job in stuff.jobs {
    print(job.title)
    print(job.description)
    print(job.img)
    for type in job.criteria {
        print(" - \(type)")
    }
}

to parse the results

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Feels like voodoo magic. stuff.filters and stuff.jobs holds the data I am seeking. – Alex Aug 10 '18 at 04:13
  • Yes, yes it does, but it's (very) welcome change from every thing that had to be done in previous, event though SwiftyJSON is awesome, this is much better - IMHO – MadProgrammer Aug 10 '18 at 04:18
  • Side note to anyone passing through this question/answer: It wasn't obvious to me for a split second, but the "structure" of your JSON needs to match that of the struct's involved. For example, if I choose to change "jobs" to "abc" in the JSON file, the struct needs to change as well ("let jobs" becomes "let abc") . – Alex Aug 12 '18 at 00:13
  • Also, I used https://stackoverflow.com/a/47681156/290196 this answer when dealing with building my nested arrays. – Alex Aug 12 '18 at 00:14
  • @Alex You "might" be able to code your own "coder", which is demonstrated in the "Customising Key Names" section of [Ultimate Guide to JSON Parsing with Swift 4](https://benscheirman.com/2017/06/swift-json/) ;) – MadProgrammer Aug 12 '18 at 00:15
1

You can implement Codable protocol to parse response. use your json response instead of this

let url = Bundle.main.url(forResource: "data", withExtension: "json")
let data = NSData(contentsOf: url!)

i used this for playground for testing.

struct Root: Codable {
   let jobs: [Jobs]
   let filters: [Filters]

private enum CodingKeys: String, CodingKey {
    case jobs = "jobs"
    case filters = "filters"
 }
}

struct Filters: Codable {
    let name: String?
    let typees: String?
}

struct Jobs: Codable {
     let title: String?
     let description: String?
     let criteria: [String]?
     let img: String? 
}

let url = Bundle.main.url(forResource: "data", withExtension: "json")
let data = NSData(contentsOf: url!)


do {
      let root = try JSONDecoder().decode(Root.self, from: data as! Data)

      if let name = root.jobs.first?.title {
      print(name)
      }


} catch let error as NSError {

   print(error.description)
}
Muhammad Shauket
  • 2,643
  • 19
  • 40