A simple and clean way to convert a JSON string to Object in Swift

I was looking for days to convert a fairly simple JSON string to an object type in Swift, but to no avail.

Here is the code to call the web service:

func GetAllBusiness() { Alamofire.request(.GET, "http://MyWebService/").responseString { (request, response, string, error) in println(string) } } 

I have a quick Business.swift structure:

 struct Business { var Id : Int = 0 var Name = "" var Latitude = "" var Longitude = "" var Address = "" } 

Here is my deployed testing service:

 [ { "Id": 1, "Name": "A", "Latitude": "-35.243256", "Longitude": "149.110701", "Address": null }, { "Id": 2, "Name": "B", "Latitude": "-35.240592", "Longitude": "149.104843", "Address": null } ... ] 

It would be nice if someone guides me through this.

Thank.

+64
json swift
Sep 02 '14 at 10:23
source share
14 answers

Here are some tips to get you started with a simple example.

You have the following JSON Array String (similar to yours), for example:

  var list:Array<Business> = [] // left only 2 fields for demo struct Business { var id : Int = 0 var name = "" } var jsonStringAsArray = "[\n" + "{\n" + "\"id\":72,\n" + "\"name\":\"Batata Cremosa\",\n" + "},\n" + "{\n" + "\"id\":183,\n" + "\"name\":\"Caldeirada de Peixes\",\n" + "},\n" + "{\n" + "\"id\":76,\n" + "\"name\":\"Batata com Cebola e Ervas\",\n" + "},\n" + "{\n" + "\"id\":56,\n" + "\"name\":\"Arroz de forma\",\n" + "}]" // convert String to NSData var data: NSData = jsonStringAsArray.dataUsingEncoding(NSUTF8StringEncoding)! var error: NSError? // convert NSData to 'AnyObject' let anyObj: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions(0), error: &error) println("Error: \(error)") // convert 'AnyObject' to Array<Business> list = self.parseJson(anyObj!) //=============== func parseJson(anyObj:AnyObject) -> Array<Business>{ var list:Array<Business> = [] if anyObj is Array<AnyObject> { var b:Business = Business() for json in anyObj as Array<AnyObject>{ b.name = (json["name"] as AnyObject? as? String) ?? "" // to get rid of null b.id = (json["id"] as AnyObject? as? Int) ?? 0 list.append(b) }// for } // if return list }//func 

[EDIT]

To get rid of null, changed to:

 b.name = (json["name"] as AnyObject? as? String) ?? "" b.id = (json["id"] as AnyObject? as? Int) ?? 0 

See also References Coalescence Operator (aka ?? )

Hope this helps you figure out

+49
02 Sep '14 at 11:42 on
source share

for quick 3/4

 extension String { func toJSON() -> Any? { guard let data = self.data(using: .utf8, allowLossyConversion: false) else { return nil } return try? JSONSerialization.jsonObject(with: data, options: .mutableContainers) } } 

Usage example:

  let dict = myString.toJSON() as? [String:AnyObject] // can be any type here 
+28
Feb 21 '17 at 23:46 on
source share

As a simple line extension, should be enough:

 extension String { var parseJSONString: AnyObject? { let data = self.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) if let jsonData = data { // Will return an object or nil if JSON decoding fails return NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers, error: nil) } else { // Lossless conversion of the string was not possible return nil } } } 

Then:

 var jsonString = "[\n" + "{\n" + "\"id\":72,\n" + "\"name\":\"Batata Cremosa\",\n" + "},\n" + "{\n" + "\"id\":183,\n" + "\"name\":\"Caldeirada de Peixes\",\n" + "},\n" + "{\n" + "\"id\":76,\n" + "\"name\":\"Batata com Cebola e Ervas\",\n" + "},\n" + "{\n" + "\"id\":56,\n" + "\"name\":\"Arroz de forma\",\n" + "}]" let json: AnyObject? = jsonString.parseJSONString println("Parsed JSON: \(json!)") println("json[3]: \(json![3])") /* Output: Parsed JSON: ( { id = 72; name = "Batata Cremosa"; }, { id = 183; name = "Caldeirada de Peixes"; }, { id = 76; name = "Batata com Cebola e Ervas"; }, { id = 56; name = "Arroz de forma"; } ) json[3]: { id = 56; name = "Arroz de forma"; } */ 
+25
Dec 03 '14 at 10:28
source share

I wrote a library that simplifies working with JSON data and deserialization in Swift. You can get it here: https://github.com/isair/JSONHelper

Change: I updated my library, now you can only do this with this:

 class Business: Deserializable { var id: Int? var name = "N/A" // This one has a default value. required init(data: [String: AnyObject]) { id <-- data["id"] name <-- data["name"] } } var businesses: [Business]() Alamofire.request(.GET, "http://MyWebService/").responseString { (request, response, string, error) in businesses <-- string } 

Old answer:

First, instead of using .responseString, use .response to get the response object. Then change your code to:

 func getAllBusinesses() { Alamofire.request(.GET, "http://MyWebService/").response { (request, response, data, error) in var businesses: [Business]? businesses <-- data if businesses == nil { // Data was not structured as expected and deserialization failed, do something. } else { // Do something with your businesses array. } } } 

And you need to make a business class like this:

 class Business: Deserializable { var id: Int? var name = "N/A" // This one has a default value. required init(data: [String: AnyObject]) { id <-- data["id"] name <-- data["name"] } } 

You can find the full documentation on my GitHub repository. Have some fun!

+7
03 Sep
source share

For Swift 4

I used @ Passkit logic, but I had to upgrade according to Swift 4




Step.1 Created extension for String Class

 import UIKit extension String { var parseJSONString: AnyObject? { let data = self.data(using: String.Encoding.utf8, allowLossyConversion: false) if let jsonData = data { // Will return an object or nil if JSON decoding fails do { let message = try JSONSerialization.jsonObject(with: jsonData, options:.mutableContainers) if let jsonResult = message as? NSMutableArray { print(jsonResult) return jsonResult //Will return the json array output } else { return nil } } catch let error as NSError { print("An error occurred: \(error)") return nil } } else { // Lossless conversion of the string was not possible return nil } } } 



Step.2 This is how I used in my view controller

 var jsonString = "[\n" + "{\n" + "\"id\":72,\n" + "\"name\":\"Batata Cremosa\",\n" + "},\n" + "{\n" + "\"id\":183,\n" + "\"name\":\"Caldeirada de Peixes\",\n" + "},\n" + "{\n" + "\"id\":76,\n" + "\"name\":\"Batata com Cebola e Ervas\",\n" + "},\n" + "{\n" + "\"id\":56,\n" + "\"name\":\"Arroz de forma\",\n" + "}]" //Convert jsonString to jsonArray let json: AnyObject? = jsonString.parseJSONString print("Parsed JSON: \(json!)") print("json[2]: \(json![2])") 

All rights belong to the original user, I just updated the latest version of Swift

+6
Apr 12 '16 at 12:00
source share

Swift 4 parses JSON much more elegantly. Just accept the encoded protocol for your structure according to this simplified example:

 struct Business: Codable { let id: Int let name: String } 

To parse a JSON array, you tell the decoder what the data array objects are.

 let parsedData = decoder.decode([Business].self, from: data) 

Here is a complete working example:

 import Foundation struct Business: Codable { let id: Int let name: String } // Generating the example JSON data: let originalObjects = [Business(id: 0, name: "A"), Business(id: 1, name: "B")] let encoder = JSONEncoder() let data = try! encoder.encode(originalObjects) // Parsing the data: let decoder = JSONDecoder() let parsedData = try! decoder.decode([Business].self, from: data) 

For more information, check out this great guide .

+5
Nov 02 '17 at 22:40
source share

For iOS 10 and Swift 3 , using Alamofire and Gloss :

 Alamofire.request("http://localhost:8080/category/en").responseJSON { response in if let data = response.data { if let categories = [Category].from(data: response.data) { self.categories = categories self.categoryCollectionView.reloadData() } else { print("Casting error") } } else { print("Data is null") } } 

and here is the category class

 import Gloss struct Category: Decodable { let categoryId: Int? let name: String? let image: String? init?(json: JSON) { self.categoryId = "categoryId" <~~ json self.name = "name" <~~ json self.image = "image" <~~ json } } 

IMO, this is by far the most elegant solution.

+4
Mar 18 '17 at 2:38 on
source share
 let jsonString = "{\"id\":123,\"Name\":\"Munish\"}" 

Convert string to NSData strong>

  var data: NSData =jsonString.dataUsingEncoding(NSUTF8StringEncoding)! var error: NSError? 

Convert NSData to AnyObject

 var jsonObject: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.allZeros, error: &error) println("Error: \\(error)") let id = (jsonObject as! NSDictionary)["id"] as! Int let name = (jsonObject as! NSDictionary)["name"] as! String println("Id: \\(id)") println("Name: \\(name)") 
+2
May 24 '15 at 6:07
source share

I like the RDC answer, but why did the JSON constraint return to only have arrays at the top level? I needed to enable the dictionary at the top level, so I changed it this way:

 extension String { var parseJSONString: AnyObject? { let data = self.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) if let jsonData = data { // Will return an object or nil if JSON decoding fails do { let message = try NSJSONSerialization.JSONObjectWithData(jsonData, options:.MutableContainers) if let jsonResult = message as? NSMutableArray { return jsonResult //Will return the json array output } else if let jsonResult = message as? NSMutableDictionary { return jsonResult //Will return the json dictionary output } else { return nil } } catch let error as NSError { print("An error occurred: \(error)") return nil } } else { // Lossless conversion of the string was not possible return nil } } 
+2
Jul 08 '16 at 23:14
source share

For Swift 4, I wrote this extension using the Codable protocol:

 struct Business: Codable { var id: Int var name: String } extension String { func parse<D>(to type: D.Type) -> D? where D: Decodable { let data: Data = self.data(using: .utf8)! let decoder = JSONDecoder() do { let _object = try decoder.decode(type, from: data) return _object } catch { return nil } } } var jsonString = "[\n" + "{\n" + "\"id\":72,\n" + "\"name\":\"Batata Cremosa\",\n" + "},\n" + "{\n" + "\"id\":183,\n" + "\"name\":\"Caldeirada de Peixes\",\n" + "},\n" + "{\n" + "\"id\":76,\n" + "\"name\":\"Batata com Cebola e Ervas\",\n" + "},\n" + "{\n" + "\"id\":56,\n" + "\"name\":\"Arroz de forma\",\n" + "}]" let businesses = jsonString.parse(to: [Business].self) 
+2
May 7 '18 at 18:16
source share

You can use swift.quicktype.io to convert JSON to struct or class . Even you can mention the fast version of genrate code.

JSON example:

 { "message": "Hello, World!" } 

Generated Code:

 import Foundation typealias Sample = OtherSample struct OtherSample: Codable { let message: String } // Serialization extensions extension OtherSample { static func from(json: String, using encoding: String.Encoding = .utf8) -> OtherSample? { guard let data = json.data(using: encoding) else { return nil } return OtherSample.from(data: data) } static func from(data: Data) -> OtherSample? { let decoder = JSONDecoder() return try? decoder.decode(OtherSample.self, from: data) } var jsonData: Data? { let encoder = JSONEncoder() return try? encoder.encode(self) } var jsonString: String? { guard let data = self.jsonData else { return nil } return String(data: data, encoding: .utf8) } } extension OtherSample { enum CodingKeys: String, CodingKey { case message } } 
+1
Oct. 31 '17 at 9:54 on
source share

Using the SwiftyJSON library, you can do this:

 if let path : String = Bundle.main.path(forResource: "tiles", ofType: "json") { if let data = NSData(contentsOfFile: path) { let optData = try? JSON(data: data as Data) guard let json = optData else { return } for (_, object) in json { let name = object["name"].stringValue print(name) } } } 
+1
Mar 26 '18 at 0:35
source share

SWIFT4 is a simple and elegant way to decode JSON strings in Struct.

The first step is to encode the string into .utf8 encoded data.

How to decode your data in YourDataStruct.

 struct YourDataStruct: Codable { let type, id: String init(_ json: String, using encoding: String.Encoding = .utf8) throws { guard let data = json.data(using: encoding) else { throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil) } try self.init(data: data) } init(data: Data) throws { self = try JSONDecoder().decode(YourDataStruct.self, from: data) } } do { let successResponse = try WSDeleteDialogsResponse(response) } } catch {} 
0
Feb 19 '19 at 14:41
source share

Here is an example for you to make things simpler and easier. My String data in my database is a JSON file that looks like this:

 [{"stype":"noun","sdsc":"careless disregard for consequences","swds":"disregard, freedom, impulse, licentiousness, recklessness, spontaneity, thoughtlessness, uninhibitedness, unrestraint, wantonness, wildness","anwds":"restraint, self-restraint"},{"stype":"verb","sdsc":"leave behind, relinquish","swds":"abdicate, back out, bail out, bow out, chicken out, cop out, cut loose, desert, discard, discontinue, ditch, drop, drop out, duck, dump, dust, flake out, fly the coop, give up the ship, kiss goodbye, leave, leg it, let go, opt out, pull out, quit, run out on, screw, ship out, stop, storm out, surrender, take a powder, take a walk, throw over, vacate, walk out on, wash hands of, withdraw, yield","anwds":"adopt, advance, allow, assert, begin, cherish, come, continue, defend, favor, go, hold, keep, maintain, persevere, pursue, remain, retain, start, stay, support, uphold"},{"stype":"verb","sdsc":"leave in troubled state","swds":"back out, desert, disown, forsake, jilt, leave, leave behind, quit, reject, renounce, throw over, walk out on","anwds":"adopt, allow, approve, assert, cherish, come, continue, defend, favor, keep, pursue, retain, stay, support, uphold"}] 

To load this JSON string data, follow these simple steps. First create a class for my MoreData object as follows:

 class MoreData { public private(set) var stype : String public private(set) var sdsc : String public private(set) var swds : String public private(set) var anwds : String init( stype : String, sdsc : String, swds : String, anwds : String) { self.stype = stype self.sdsc = sdsc self.swds = swds self.anwds = anwds }} 

Secondly, create my String extension for my JSON string as follows:

 extension String { func toJSON() -> Any? { guard let data = self.data(using: .utf8, allowLossyConversion: false) else { return nil } return try? JSONSerialization.jsonObject(with: data, options: .mutableContainers) }} 

Third, create the My Srevices class to process my string data as follows:

 class Services { static let instance: Services = Services() func loadMoreDataByString(byString: String) -> [MoreData]{ var myVariable = [MoreData]() guard let ListOf = byString.toJSON() as? [[String: AnyObject]] else { return [] } for object in ListOf { let stype = object["stype"] as? String ?? "" let sdsc = object["sdsc"] as? String ?? "" let swds = object["swds"] as? String ?? "" let anwds = object["anwds"] as? String ?? "" let myMoreData = MoreData(stype : stype, sdsc : sdsc, swds : swds, anwds : anwds) myVariable.append(myMoreData) } return myVariable }} 

Finally, call this function from the view controller to load the data into the table view as follows:

  func handlingJsonStringData(){ moreData.removeAll(keepingCapacity: false) moreData = Services.instance.loadMoreDataByString(byString: jsonString) print(self.moreData.count) tableView.reloadData() } 
0
Mar 28 '19 at 11:01
source share



All Articles