I have been searching for days to convert a fairly simple JSON string to an object type in Swift but with no avail.
Here is the code for web service call:
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)
As simple String extension should suffice:
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";
}
*/
I wrote a library which makes working with json data and deserialization a breeze in Swift. You can get it here: https://github.com/isair/JSONHelper
Edit: I updated my library, you can now do it with just 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 a 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 repo. Have fun!
SWIFT4 - Easy and elegant way of decoding JSON strings to Struct.
First step - encode String to Data with .utf8 encoding.
Than decode your Data to 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 {}
You can use swift.quicktype.io for converting JSON
to either struct
or class
. Even you can mention version of swift to genrate code.
Example JSON:
{
"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
}
}
for swift 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)
}
}
Example Usage:
let dict = myString.toJSON() as? [String:AnyObject] // can be any type here