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.

1

2 Answers 2

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

Sign up to request clarification or add additional context in comments.

5 Comments

Feels like voodoo magic. stuff.filters and stuff.jobs holds the data I am seeking.
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
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") .
Also, I used stackoverflow.com/a/47681156/290196 this answer when dealing with building my nested arrays.
@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 ;)
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)
}

Comments

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.