Simple and clean way to convert JSON string to Object in Swift
Here are some tips how to begin with simple example.
Consider you have following JSON Array String (similar to yours) like:
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 Reference of Coalescing Operator (aka ??
)
Hope it will help you to sort things out,
How can I parse a JSON string in swift?
Here is how you can decode your response:
typealias YourDecodedObject = [ClassObject]
struct ClassObject: Codable {
let welcomeClass: String?
let classToken: String?
let teacherName: String?
let room: String?
let grade: String?
enum CodingKeys: String, CodingKey {
case welcomeClass = "class"
case classToken, teacherName, room, grade
}
}
func decodeResponseFrom(data: Data?) {
if let data = data {
do {
let decodedObject = try JSONDecoder().decode(YourDecodedObject.self, from: data)
} catch {
print("could not decode ❌")
}
}
}
Convert Json string to Json object in Swift 4
The problem is that you thought your jsonString is a dictionary. It's not.
It's an array of dictionaries.
In raw json strings, arrays begin with [
and dictionaries begin with {
.
I used your json string with below code :
let string = "[{\"form_id\":3465,\"canonical_name\":\"df_SAWERQ\",\"form_name\":\"Activity 4 with Images\",\"form_desc\":null}]"
let data = string.data(using: .utf8)!
do {
if let jsonArray = try JSONSerialization.jsonObject(with: data, options : .allowFragments) as? [Dictionary<String,Any>]
{
print(jsonArray) // use the json here
} else {
print("bad json")
}
} catch let error as NSError {
print(error)
}
and I am getting the output :
[["form_desc": <null>, "form_name": Activity 4 with Images, "canonical_name": df_SAWERQ, "form_id": 3465]]
What is the best way to convert JSON into swift object, Checking keys and values both
You should have a look at the Codable
protocol: The following Playground shows what happens, when you try to parse a Json, that is missing a particular key.
//: Playground - noun: a place where people can play
import Foundation
At first, we create our ProfileModel class and mock a related json.
class ProfileModel: Codable {
//...
var _firstName: String?
var _lastName: String?
}
let profile = ProfileModel()
profile._firstName = "Hans"
profile._lastName = "Peter"
let json = try! JSONEncoder().encode(profile)
Parsing works as expected:
do {
let profileAgain = try JSONDecoder().decode(ProfileModel.self, from: json)
print(profileAgain._firstName) // "Optional("Hans")\n"
print(profileAgain._lastName) // "Optional("Peter")\n"
} catch {
print("something went wrong")
}
So what happens, when we add another property to our class (_phone_no), that is not included in our Json? Nothing really changes, if this new property is optional:
class AnotherProfileModel: Codable {
//...
var _firstName: String?
var _lastName: String?
var _phone_no: Int?
}
do {
let anotherProfile = try JSONDecoder().decode(AnotherProfileModel.self, from: json)
print(anotherProfile._firstName) // "Optional("Hans")\n"
print(anotherProfile._lastName) // "Optional("Peter")\n"
print(anotherProfile._phone_no) // "nil\n"
} catch {
print("something went wrong")
}
But if this property is not an optional, the decoder will throw an error:
class AndYetAnotherProfileModel: Codable {
//...
var _firstName: String?
var _lastName: String?
var _phone_no: Int
}
do {
let andYetAnotherProfileModel = try JSONDecoder().decode(AndYetAnotherProfileModel.self, from: json)
} catch {
print("something went wrong") // "something went wrong\n"
}
I hope this working example will help you, to get a better understanding of the Codable
protocol :)
change JSON to String in Swift
Swift 3,4 :
The given JSON format is Array
of String
.
if let json = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String]{
let firstElement = json?.first ?? "Element Not Found!"
print(firstElement)
}
Swift 4:
if let json = try? JSONDecoder().decode(Array<String>.self, from: data){
let firstElement = json.first ?? "First Element Not Found!"
print(firstElement)
}
Note:
If your the Array
contains more than one String
. Here,urls
is the class
variable. i.e.,var urls = [String]()
Swift 3,4 :
if let json = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String]{
if json != nil{
self.urls = json!
}
print(self.urls)
}
Swift 4:
if let json = try? JSONDecoder().decode(Array<String>.self, from: data){
self.urls = json
}
How to parse json in swift (convert json string to string)
You get a json string so you can try
let jsonstring = "\"asdf\""
let data = jsonstring.data(using: .utf8)
do {
if let str = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) as? String {
print(str)
}
}
catch let caught as NSError
{
}
How to serialize or convert Swift objects to JSON?
In Swift 4, you can inherit from the Codable
type.
struct Dog: Codable {
var name: String
var owner: String
}
// Encode
let dog = Dog(name: "Rex", owner: "Etgar")
let jsonEncoder = JSONEncoder()
let jsonData = try jsonEncoder.encode(dog)
let json = String(data: jsonData, encoding: String.Encoding.utf16)
// Decode
let jsonDecoder = JSONDecoder()
let secondDog = try jsonDecoder.decode(Dog.self, from: jsonData)
How do I convert JSON object to CLLOCATIONDEGREES?
The error message
Cast from JSON to unrelated object CLLocationDegrees (aka Double) always fails
is pretty clear, subscripted JSON
in the SwiftyJSON
library returns JSON
. You have to get the doubleValue
(CLLocationDegrees
is a type alias of Double
)
for (key,subJson) in json { // don't annotate types unless the compiler tells you
let lat = subJson["latitude"].doubleValue
let lng = subJson["longitude"].doubleValue
// do something with lat and lng
}
Serialize JSON string that contains escaped (backslash and double quote) Swift return Badly formed object
First of all if you wrap the JSON in the literal string syntax of Swift 4 you have to escape the backslashes.
let jsonStr = """
{
"status": "success",
"data": "{\\"name\\":\\"asd\\",\\"address\\":\\"Street 1st\\"}"
}
"""
You got nested JSON. The value for key data
is another JSON string which must be deserialized separately
let jsonData = Data(jsonStr.utf8)
do {
if let object = try JSONSerialization.jsonObject(with: jsonData) as? [String:String] {
print(object)
if let dataString = object["data"] as? String {
let dataStringData = Data(dataString.utf8)
let dataObject = try JSONSerialization.jsonObject(with: dataStringData) as? [String:String]
print(dataObject)
}
}
} catch {
print(error)
}
Or – with a bit more effort but – much more comfortable with the (De)Codable
protocol
struct Response : Decodable {
private enum CodingKeys : String, CodingKey { case status, data }
let status : String
let person : Person
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
status = try container.decode(String.self, forKey: .status)
let dataString = try container.decode(String.self, forKey: .data)
person = try JSONDecoder().decode(Person.self, from: Data(dataString.utf8))
}
}
struct Person : Decodable {
let name, address : String
}
let jsonStr = """
{
"status": "success",
"data": "{\\"name\\":\\"asd\\",\\"address\\":\\"Street 1st\\"}"
}
"""
let jsonData = Data(jsonStr.utf8)
do {
let result = try JSONDecoder().decode(Response.self, from: jsonData)
print(result)
} catch {
print(error)
}
Related Topics
How to Throttle Search (Based on Typing Speed) in iOS Uisearchbar
Autolayout Is Ignored in Custom Uitableviewcell
How to Detect When Avplayer Video Ends Playing
Ios8 Photos Framework: How to Get the Name(Or Filename) of a Phasset
Using Updatechildvalues to Delete from Firebase
How to Use a Uisegmentedcontrol to Switch Views
How to Distribute My App for Any Device Without Udid
Xcode 6 - Launch Simulator from Command Line
Instead of Push Segue How to Replace View Controller (Or Remove from Navigation Stack)
Saving Image to Documents Directory and Retrieving for Email Attachment
iOS Nsdate() Returns Incorrect Time
Launch Apple Mail App from Within My Own App
Application Crashed While Importing Songs from Ipod Library in iPhone for iOS 5.0
How to Save a Uicolor with Userdefaults
Creating a Reusable Uiview with Xib (And Loading from Storyboard)