JSON Parsing in Swift 3

前端 未结 8 791
暖寄归人
暖寄归人 2020-12-01 11:05

Has anyone been able to find a way to parse through JSON files in Swift 3? I have been able to get the data to return but I am unsuccessful when it comes to breaking the dat

相关标签:
8条回答
  • 2020-12-01 11:15
     override func viewDidLoad() {
            super.viewDidLoad()
            let url=URL(string:"http://api.androidhive.info/contacts/")
            do {
                let allContactsData = try Data(contentsOf: url!)
                let allContacts = try JSONSerialization.jsonObject(with: allContactsData, options: JSONSerialization.ReadingOptions.allowFragments) as! [String : AnyObject]
                if let arrJSON = allContacts["contacts"] {
                    for index in 0...arrJSON.count-1 {
                        let aObject = arrJSON[index] as! [String : AnyObject]
                        names.append(aObject["name"] as! String)
                        contacts.append(aObject["email"] as! String)
                    }
                }
                print(names)
                print(contacts)
                self.tableView.reloadData()
            }
            catch {
            }
        }
    
    0 讨论(0)
  • 2020-12-01 11:25

    JSON Parsing in swift 4 using Decodable Protocol :

    I create a mocky file using your json object :

    http://www.mocky.io/v2/5a280c282f0000f92c0635e6

    Here is the code to parse the JSON :

    Model Creation :

    import UIKit
    
    struct Item : Decodable { 
    // Properties must be the same name as specified in JSON , else it will return nil
    var Number : String
    var Name : String
    }
    
    struct Language : Decodable {
     var Field : [Item]
    }
    
    struct Result : Decodable {
     var Language : Language
    }
    

    You can use optional in the model if you are uncertain that something might be missing in JSON file.

    This is the parsing Logic :

    class ViewController: UIViewController {
    
    let url = "http://www.mocky.io/v2/5a280c282f0000f92c0635e6"
    
    private func parseJSON() {
    
        guard let url = URL(string: url) else { return }
    
        let session = URLSession.shared.dataTask(with: url) { (data, response, error) in
            guard let data = data else { return }
            guard let result = try? JSONDecoder().decode(Result.self, from: data) else { return }
            print("\n\nResult : \(result)")
        }
        session.resume()
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        parseJSON()
    }
    }
    

    The Print Output :

     Result : Result(Language: JSON_Parsing.Language(Field: [JSON_Parsing.Item(Number: "976", Name: "Test"), JSON_Parsing.Item(Number: "977", Name: "Test")]))
    

    This the github Project link. You can check.

    0 讨论(0)
  • 2020-12-01 11:28

    Have you tried JSONSerialization.jsonObject(with:options:)?

    var jsonString = "{" +
        "\"Language\": {" +
        "\"Field\":[" +
        "{" +
        "\"Number\":\"976\"," +
        "\"Name\":\"Test\"" +
        "}," +
        "{" +
        "\"Number\":\"977\"," +
        "\"Name\":\"Test\"" +
        "}" +
        "]" +
        "}" +
        "}"
    
    var data = jsonString.data(using: .utf8)!
    
    let json = try? JSONSerialization.jsonObject(with: data)
    

    Swift sometimes produces some very odd syntax.

    if let number = json?["Language"]??["Field"]??[0]?["Number"] as? String {
        print(number)
    }
    

    Everything in the JSON object hierarchy ends up getting wrapped as an optional (ie. AnyObject?). Array<T> subscript returns a non-optional T. For this JSON, which is wrapped in an optional, array subscript returns Optional<AnyObject>. However, Dictionary<K, V> subscript returns an Optional<V>. For this JSON, subscript returns the very odd looking Optional<Optional<AnyObject>> (ie. AnyObject??).

    • json is an Optional<AnyObject>.
    • json?["Language"] returns an Optional<Optional<AnyObject>>.
    • json?["Language"]??["Field"] returns an Optional<Optional<AnyObject>>.
    • json?["Language"]??["Field"]??[0] returns an Optional<AnyObject>.
    • json?["Language"]??["Field"]??[0]?["Number"] returns an Optional<Optional<AnyObject>>.
    • json?["Language"]??["Field"]??[0]?["Number"] as? String returns an Optional<String>.

    The Optional<String> is then used by the if let syntax to product a String.


    Final note: iterating the field array looks like this.

    for field in json?["Language"]??["Field"] as? [AnyObject] ?? [] {
        if let number = field["Number"] as? String {
            print(number)
        }
    }
    

    Swift 4 Update

    Swift 4 makes this all much easier to deal with. Again we will start with your test data (""" makes this so much nicer).

    let data = """
    {
      "Language": {
    
        "Field":[
              {
              "Number":"976",
              "Name":"Test"
              },
              {
              "Number":"977",
              "Name":"Test"
              }
           ]
       }
    }
    """.data(using: .utf8)!
    

    Next we can define classes around the objects used in your JSON.

    struct Object: Decodable {
        let language: Language
        enum CodingKeys: String, CodingKey { case language="Language" }
    }
    
    struct Language: Decodable {
        let fields: [Field]
        enum CodingKeys: String, CodingKey { case fields="Field" }
    }
    
    struct Field: Decodable {
        let number: String
        let name: String
        enum CodingKeys: String, CodingKey { case number="Number"; case name="Name" }
    }
    

    The CodingKeys enum is how struct properties are mapped to JSON object member strings. This mapping is done automagically by Decodable.


    Parsing the JSON now is simple.

    let object = try! JSONDecoder().decode(Object.self, from: data)
    
    print(object.language.fields[0].name)
    
    for field in object.language.fields {
        print(field.number)
    }
    
    0 讨论(0)
  • 2020-12-01 11:29

    Shoving JSON into a string manually is a pita. Why don't you just put the JSON into a file and read that in?

    Swift 3:

    let bundle = Bundle(for: type(of: self))
        if let theURL = bundle.url(forResource: "response", withExtension: "json") {
            do {
                let data = try Data(contentsOf: theURL)
                if let parsedData = try? JSONSerialization.jsonObject(with: data) as! [String:Any] {
                    grok(parsedData)
                }
            } catch {
                print(error)
            }
        }
    
    0 讨论(0)
  • 2020-12-01 11:29

    JSON Parsing using Swift 4 in Simple WAY

       let url = URL(string: "http://mobileappdevelop.co/TIPIT/webservice/get_my_groups?user_id=5")
        URLSession.shared.dataTask(with:url!, completionHandler: {(data, response, error) in
            guard let data = data, error == nil else { return }
    
            do {
                let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [String:Any]
    
                 print(json)
    
                let posts =  json["Field"] as? [[String: Any]] ?? []
                print(posts)
            } catch let error as NSError {
                print(error)
            }
    
        }).resume()
    
    }
    
    0 讨论(0)
  • 2020-12-01 11:29

    Use SwiftJson library. I think its very easy way to parse.

    let count: Int? = json["Field"].array?.count
    if let ct = count {            
        for index in 0...ct-1{
            let number = json ["Field"][index]["number"].string
            let name = json ["Field"][index]["name"].string 
    

    ....

    like this .

    0 讨论(0)
提交回复
热议问题