How to parse a JSON file in swift?

I have a JSON file, want to parse and use list of objects in table view. Can any one share the code to parse JSON file in swift.


Solution 1:

This answer was last revised for Swift 5.3 and iOS 14.4 SDK.


Given some already obtained JSON data, you can use JSONDecoder to decode it into your Decodable model (or a collection of models).

let data: Data = /* obtain your JSON data */
let model = try JSONDecoder().decode(Model.self, from: data)

Such model must conform to the Decodable protocol and contain correct mapping between properties and JSON dictionary keys. As an example, consider the following JSON array containing search results of cities beginning with "Wa".

[
    {
        "id": 123,
        "city": "Washington",
        "region": "D.C.",
        "country": "United States"
    },
    {
        "id": 456,
        "city": "Warsaw",
        "region": "Mazowieckie",
        "country": "Poland"
    },
    ...
]

For that, you need to create a model that contains the correct properties of correct types. If you're using a web API, its documentation will be of great help here.

struct SearchResult: Decodable {
    let id: Int
    let city: String
    let region: String
    let country: String
}

Then decode the data with JSONDecoder:

let results = try JSONDecoder().decode([SearchResult].self, from: data)

Given a new array of decoded search results, call one of UITableView's functions to reload its data. Note that the decode function can throw an error which you must somehow handle.

To learn more about decoding custom types in Swift and more advanced usage of the Codable APIs, I recommend checking out this documentation article.

Solution 2:

Making the API Request

var request: NSURLRequest = NSURLRequest(URL: url)
var connection: NSURLConnection = NSURLConnection(request: request, delegate: self, startImmediately: false)

Preparing for the response

Declare an array as below

var data: NSMutableData = NSMutableData()

Receiving the response

1.

func connection(didReceiveResponse: NSURLConnection!, didReceiveResponse response: NSURLResponse!) {
   // Received a new request, clear out the data object
   self.data = NSMutableData()
}

2.

func connection(connection: NSURLConnection!, didReceiveData data: NSData!) {
   // Append the received chunk of data to our data object
   self.data.appendData(data)
}

3.

func connectionDidFinishLoading(connection: NSURLConnection!) {
   // Request complete, self.data should now hold the resulting info
   // Convert the retrieved data in to an object through JSON deserialization
   var err: NSError
   var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary

   if jsonResult.count>0 && jsonResult["results"].count>0 {
      var results: NSArray = jsonResult["results"] as NSArray
      self.tableData = results
      self.appsTableView.reloadData()

   }
}

When NSURLConnection receives a response, we can expect the didReceiveResponse method to be called on our behalf. At this point we simply reset our data by saying self.data = NSMutableData(), creating a new empty data object.

After a connection is made, we will start receiving data in the method didReceiveData. The data argument being passed in here is where all our juicy information comes from. We need to hold on to each chunk that comes in, so we append it to the self.data object we cleared out earlier.

Finally, when the connection is done and all data has been received, connectionDidFinishLoading is called and we’re ready to use the data in our app. Hooray!

The connectionDidFinishLoading method here uses the NSJSONSerialization class to convert our raw data in to useful Dictionary objects by deserializing the results from your Url.

Solution 3:

I just wrote a class called JSON, which makes JSON handling in Swift as easy as JSON object in ES5.

  • https://github.com/dankogai/swift-json/

Turn your swift object to JSON like so:

let obj:[String:AnyObject] = [
    "array": [JSON.null, false, 0, "",[],[:]],
    "object":[
        "null":   JSON.null,
        "bool":   true,
        "int":    42,
        "double": 3.141592653589793,
        "string": "a α\t弾\n𪚲",
        "array":  [],
        "object": [:]
    ],
    "url":"http://blog.livedoor.com/dankogai/"
]

let json = JSON(obj)
json.toString()

...or string...

let json = JSON.parse("{\"array\":[...}")

...or URL.

let json = JSON.fromURL("http://api.dan.co.jp/jsonenv")
Tree Traversal

Just traverse elements via subscript:

json["object"]["null"].asNull       // NSNull()
// ...
json["object"]["string"].asString   // "a α\t弾\n𪚲"
json["array"][0].asNull             // NSNull()
json["array"][1].asBool             // false
// ...

Just like SwiftyJSON you don't worry if the subscripted entry does not exist.

if let b = json["noexistent"][1234567890]["entry"].asBool {
    // ....
} else {
    let e = json["noexistent"][1234567890]["entry"].asError
    println(e)
}

If you are tired of subscripts, add your scheme like so:

//// schema by subclassing
class MyJSON : JSON {
    init(_ obj:AnyObject){ super.init(obj) }
    init(_ json:JSON)  { super.init(json) }
    var null  :NSNull? { return self["null"].asNull }
    var bool  :Bool?   { return self["bool"].asBool }
    var int   :Int?    { return self["int"].asInt }
    var double:Double? { return self["double"].asDouble }
    var string:String? { return self["string"].asString }
}

And you go:

let myjson = MyJSON(obj)
myjson.object.null
myjson.object.bool
myjson.object.int
myjson.object.double
myjson.object.string
// ...

Hope you like it.

With the new xCode 7.3+ its important to add your domain to the exception list (How can I add NSAppTransportSecurity to my info.plist file?), refer to this posting for instructions, otherwise you will get a transport authority error.