iOS : Parsing JSON with Swift 2 – A Realistic Example

Okay so I wrote this blog post to help others who might be frustrated by the lack of real-world examples of parsing JSON with Swift 2. There are quite a few examples on the net you can find but (so far in my search at least) they are all way too simple to be useful when faced with some JSON with multiple levels of nested data.

Here is some JSON I downloaded from the Glasgow Smart City Car Park occupancy feed here.

{
   "version":"1.0",
   "encoding":"UTF-8",
   "d2lm$d2LogicalModel":{
      "@xmlns$d2lm":"http://datex2.eu/schema/1_0/1_0",
      "@xmlns$xsi":"http://www.w3.org/2001/XMLSchema-instance",
      "@xmlns$xalan":"http://xml.apache.org/xslt",
      "@xmlns$java":"http://xml.apache.org/xalan/java",
      "@modelBaseVersion":"1.0",
      "@xsi$schemaLocation":"http://datex2.eu/schema/1_0/1_0 http://datex2.eu/schema/1_0/1_0/DATEXIISchema_1_0_1_0.xsd",
      "d2lm$exchange":{
         "d2lm$supplierIdentification":{
            "d2lm$country":"gb",
            "d2lm$nationalIdentifier":"TIH Toolkit"
         }
      },
      "d2lm$payloadPublication":{
         "@lang":"en",
         "@xsi$type":"d2lm:SituationPublication",
         "d2lm$publicationTime":"2015-12-16T19:08:52",
         "d2lm$publicationCreator":{
            "d2lm$country":"gb",
            "d2lm$nationalIdentifier":"TIH Toolkit"
         },
         "d2lm$situation":[
            {
               "@id":"CPG25C",
               "d2lm$headerInformation":{
                  "d2lm$confidentiality":"noRestriction",
                  "d2lm$informationStatus":"real"
               },
               "d2lm$situationRecord":{
                  "@id":"CPG25C_1",
                  "@xsi$type":"d2lm:CarParks",
                  "d2lm$situationRecordCreationTime":"2015-08-24T12:29:44",
                  "d2lm$situationRecordVersion":"1",
                  "d2lm$situationRecordVersionTime":"2015-08-24T12:29:44",
                  "d2lm$situationRecordFirstSupplierVersionTime":"2015-08-24T12:29:44",
                  "d2lm$probabilityOfOccurrence":"certain",
                  "d2lm$validity":{
                     "d2lm$validityStatus":"active",
                     "d2lm$validityTimeSpecification":{
                        "d2lm$overallStartTime":"2015-08-24T12:29:44"
                     }
                  },
                  "d2lm$groupOfLocations":{
                     "d2lm$locationContainedInGroup":{
                        "@xsi$type":"d2lm:Point",
                        "d2lm$pointByCoordinates":{
                           "d2lm$pointCoordinates":{
                              "d2lm$latitude":"55.85988984843241",
                              "d2lm$longitude":"-4.282341367108816"
                           }
                        }
                     }
                  },
                  "d2lm$carParkIdentity":"SECC:CPG25C",
                  "d2lm$carParkOccupancy":"17.0",
                  "d2lm$carParkStatus":"enoughSpacesAvailable",
                  "d2lm$occupiedSpaces":"282",
                  "d2lm$totalCapacity":"1600"
               }
            },
            {
               "@id":"CPG24C",
               "d2lm$headerInformation":{
                  "d2lm$confidentiality":"noRestriction",
                  "d2lm$informationStatus":"real"
               },
               "d2lm$situationRecord":{
                  "@id":"CPG24C_1",
                  "@xsi$type":"d2lm:CarParks",
                  "d2lm$situationRecordCreationTime":"2015-08-24T12:29:44",
                  "d2lm$situationRecordVersion":"1",
                  "d2lm$situationRecordVersionTime":"2015-08-24T12:29:44",
                  "d2lm$situationRecordFirstSupplierVersionTime":"2015-08-24T12:29:44",
                  "d2lm$probabilityOfOccurrence":"certain",
                  "d2lm$validity":{
                     "d2lm$validityStatus":"active",
                     "d2lm$validityTimeSpecification":{
                        "d2lm$overallStartTime":"2015-08-24T12:29:44"
                     }
                  },
                  "d2lm$groupOfLocations":{
                     "d2lm$locationContainedInGroup":{
                        "@xsi$type":"d2lm:Point",
                        "d2lm$pointByCoordinates":{
                           "d2lm$pointCoordinates":{
                              "d2lm$latitude":"55.85966175538049",
                              "d2lm$longitude":"-4.236528758151018"
                           }
                        }
                     }
                  },
                  "d2lm$carParkIdentity":"Duke Street:CPG24C",
                  "d2lm$carParkOccupancy":"54.0",
                  "d2lm$carParkStatus":"enoughSpacesAvailable",
                  "d2lm$occupiedSpaces":"643",
                  "d2lm$totalCapacity":"1170"
               }
            }
         ]
      }
   }
}

What we want to extract are the contents of the top level elements of the “d2lm$situationRecord” tags (I have edited the original JSON to only include two records for brevity).┬áTo do this we are going to have to parse down a few levels. I had to figure out how to do this as all the examples I have seen on the net are for very simple JSON. Here is a short example swift command line program to demonstrated how it’s done.

import Foundation

var CAR_PARK_JSON : String = "{\"version\":\"1.0\",\"encoding\":\"UTF-8\",\"d2lm$d2LogicalModel\":{\"@xmlns$d2lm\":\"http://datex2.eu/schema/1_0/1_0\",\"@xmlns$xsi\":\"http://www.w3.org/2001/XMLSchema-instance\",\"@xmlns$xalan\":\"http://xml.apache.org/xslt\",\"@xmlns$java\":\"http://xml.apache.org/xalan/java\",\"@modelBaseVersion\":\"1.0\",\"@xsi$schemaLocation\":\"http://datex2.eu/schema/1_0/1_0 http://datex2.eu/schema/1_0/1_0/DATEXIISchema_1_0_1_0.xsd\",\"d2lm$exchange\":{\"d2lm$supplierIdentification\":{\"d2lm$country\":\"gb\",\"d2lm$nationalIdentifier\":\"TIH Toolkit\"}},\"d2lm$payloadPublication\":{\"@lang\":\"en\",\"@xsi$type\":\"d2lm:SituationPublication\",\"d2lm$publicationTime\":\"2015-12-16T19:08:52\",\"d2lm$publicationCreator\":{\"d2lm$country\":\"gb\",\"d2lm$nationalIdentifier\":\"TIH Toolkit\"},\"d2lm$situation\":[{\"@id\":\"CPG25C\",\"d2lm$headerInformation\":{\"d2lm$confidentiality\":\"noRestriction\",\"d2lm$informationStatus\":\"real\"},\"d2lm$situationRecord\":{\"@id\":\"CPG25C_1\",\"@xsi$type\":\"d2lm:CarParks\",\"d2lm$situationRecordCreationTime\":\"2015-08-24T12:29:44\",\"d2lm$situationRecordVersion\":\"1\",\"d2lm$situationRecordVersionTime\":\"2015-08-24T12:29:44\",\"d2lm$situationRecordFirstSupplierVersionTime\":\"2015-08-24T12:29:44\",\"d2lm$probabilityOfOccurrence\":\"certain\",\"d2lm$validity\":{\"d2lm$validityStatus\":\"active\",\"d2lm$validityTimeSpecification\":{\"d2lm$overallStartTime\":\"2015-08-24T12:29:44\"}},\"d2lm$groupOfLocations\":{\"d2lm$locationContainedInGroup\":{\"@xsi$type\":\"d2lm:Point\",\"d2lm$pointByCoordinates\":{\"d2lm$pointCoordinates\":{\"d2lm$latitude\":\"55.85988984843241\",\"d2lm$longitude\":\"-4.282341367108816\"}}}},\"d2lm$carParkIdentity\":\"SECC:CPG25C\",\"d2lm$carParkOccupancy\":\"17.0\",\"d2lm$carParkStatus\":\"enoughSpacesAvailable\",\"d2lm$occupiedSpaces\":\"282\",\"d2lm$totalCapacity\":\"1600\"}},{\"@id\":\"CPG24C\",\"d2lm$headerInformation\":{\"d2lm$confidentiality\":\"noRestriction\",\"d2lm$informationStatus\":\"real\"},\"d2lm$situationRecord\":{\"@id\":\"CPG24C_1\",\"@xsi$type\":\"d2lm:CarParks\",\"d2lm$situationRecordCreationTime\":\"2015-08-24T12:29:44\",\"d2lm$situationRecordVersion\":\"1\",\"d2lm$situationRecordVersionTime\":\"2015-08-24T12:29:44\",\"d2lm$situationRecordFirstSupplierVersionTime\":\"2015-08-24T12:29:44\",\"d2lm$probabilityOfOccurrence\":\"certain\",\"d2lm$validity\":{\"d2lm$validityStatus\":\"active\",\"d2lm$validityTimeSpecification\":{\"d2lm$overallStartTime\":\"2015-08-24T12:29:44\"}},\"d2lm$groupOfLocations\":{\"d2lm$locationContainedInGroup\":{\"@xsi$type\":\"d2lm:Point\",\"d2lm$pointByCoordinates\":{\"d2lm$pointCoordinates\":{\"d2lm$latitude\":\"55.85966175538049\",\"d2lm$longitude\":\"-4.236528758151018\"}}}},\"d2lm$carParkIdentity\":\"Duke Street:CPG24C\",\"d2lm$carParkOccupancy\":\"54.0\",\"d2lm$carParkStatus\":\"enoughSpacesAvailable\",\"d2lm$occupiedSpaces\":\"643\",\"d2lm$totalCapacity\":\"1170\"}}]}}}"

var datastring : NSString = CAR_PARK_JSON
var nsdata : NSData! = datastring.dataUsingEncoding(NSUTF8StringEncoding)

do {
    let json = try NSJSONSerialization.JSONObjectWithData(nsdata, options: .AllowFragments)
    
    let d2LogicalModel = json["d2lm$d2LogicalModel"] as! [String : AnyObject]
        
    let  payloadPublication = d2LogicalModel["d2lm$payloadPublication"] as! [String : AnyObject]
        
    let situations = payloadPublication["d2lm$situation"] as! [[String : AnyObject]]

    for situation in situations {
        
        let record = situation["d2lm$situationRecord"] as! [String : AnyObject]
        
        let carParkIdentity = record["d2lm$carParkIdentity"] as! String
        let carParkOccupancy = record["d2lm$carParkOccupancy"] as! String
        let carParkStatus = record["d2lm$carParkStatus"] as! String
        let occupiedSpaces = record["d2lm$occupiedSpaces"] as! String
        let totalCapacity = record["d2lm$totalCapacity"]as! String
        
        print("id :\(carParkIdentity), occupancy:\(carParkOccupancy), status:\(carParkStatus), capacity:\(totalCapacity), occupied:\(occupiedSpaces)\n")
    }
    
    
} catch {
    print("error serializing JSON: \(error)")
}

If you run this you should get the output

id :SECC:CPG25C, occupancy:17.0, status:enoughSpacesAvailable, capacity:1600, occupied:282

id :Duke Street:CPG24C, occupancy:54.0, status:enoughSpacesAvailable, capacity:1170, occupied:643

A few things to note:

I hope this helps someone else.

Comments

Leave a Reply