Simple and Clean Way to Convert JSON String to Object in Swift

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



Leave a reply



Submit