Json Parsing in swift 3 using Alamofire - json

I am working in swift 3. I am new to ios. I am trying to parse the json data like
My jsonVlaue is : {
data = (
{
Password = "#1234";
UserName = "<null>";
"___class" = OrderTable;
"__meta" = "{\"relationRemovalIds\":{},\"selectedProperties\":[\"UserName\",\"created\",\"name\",\"___class\",\"ownerId\",\"updated\",\"objectId\",\"Password\"],\"relatedObjects\":{}}";
created = 1483525854000;
name = TestMan;
objectId = "4316DEBA-78C1-C7BD-FFBC-3CB77D747F00";
ownerId = "<null>";
updated = "<null>";
},
{
Password = 123;
UserName = "<null>";
"___class" = OrderTable;
"__meta" = "{\"relationRemovalIds\":{},\"selectedProperties\":[\"UserName\",\"created\",\"name\",\"___class\",\"ownerId\",\"updated\",\"objectId\",\"Password\"],\"relatedObjects\":{}}";
created = 1483516868000;
name = tommy;
objectId = "29155114-C00B-5E1C-FF6F-7C828C635200";
ownerId = "<null>";
updated = "<null>";
}.......
I want only the keyvalue:"name" and that value I want to add in an Array.
I tried to do like that but my app is getting Crash. My code i slike as follows
func getLoginDetails()
{
//https://api.backendless.com/<version>/data/<table-name>/properties
Alamofire.request( HeadersClass.api.domainName + "OrderTable", method: .get, parameters: nil, encoding: JSONEncoding.default, headers: HeadersClass.allHeaders.headers).responseJSON { response in
//debugPrint(response)
if let jsonDict = response.result.value as? NSDictionary {
print("My jsonVlaue is : \(jsonDict)")
let arrayPracticeData: NSArray = jsonDict.value(forKey: "name") as! NSArray
print(arrayPracticeData)
}
}
}
Can anyone please tell me how to solve this. Thanks in Advance.

First of all in Swift use Swift's native Array and Dictionary instead of NSDictionary and NSArray.
Now to get name you need to get Data array from your JSON response Dictionary. So try something like this.
Alamofire.request( HeadersClass.api.domainName + "OrderTable", method: .get, parameters: nil, encoding: JSONEncoding.default, headers: HeadersClass.allHeaders.headers).responseJSON { response in
//debugPrint(response)
if let jsonDict = response.result.value as? [String:Any],
let dataArray = jsonDict["data"] as? [[String:Any]] {
let nameArray = dataArray.flatMap { $0["name"] as? String }
print(nameArray)
}
}
Output
["TestMan", "tommy", ...]

Related

IOS swift convert dictionary to json string creates invalid JSON

I have a json object which I receive from iOS api javascript callback and I will send the same json to php back end to validate it. In android everything works fine, but in IOS app the problem is when I receive the message.body which is json, it shows as below.
{
OrderNumber = 01869756;
"customer_key" = SLApO64gAktgmuLl;
"order_address" = "{\"address\":\"No. 7 Ogwui Road Enugu\",\"city\":\"Enugu\"}";
"order_amount" = 242550;
"order_currency" = "₦";
"order_currency_iso" = NGN;
"order_shipping" = 0;
"order_stores" = {
zOEZPU8sGCADHRbr8yw4 = {
amount = 242550;
currency = "₦";
delivery = 0;
total = 242550;
};
};
"order_subtotal" = 242550;
"order_subtotal_cent" = 24255000;
"order_tax" = "4123.35";
"order_tax_cent" = 412335;
"order_total" = "246673.35";
"order_total_cent" = 24667335;
status = 200;
}
When I pass the above IOS format to php backend json_decode($payload) it always return null. Please how do I convert this to real json format I have tried below code but it doesn't work?
let encoder = JSONEncoder()
if let jsonData = try? encoder.encode("\(message.body)") {
if let jsonString = String(data: jsonData, encoding: .utf8) {
print("dictFromJSON", jsonString)
}
}
And also I tried this
if let response = message.body as? Dictionary<String, AnyObject> {
let encoder = JSONEncoder()
if let jsonData = try? encoder.encode("\(response)") {
if let jsonString = String(data: jsonData, encoding: .utf8) {
print("dictFromJSON", jsonString)
}
}
}
But the above code output something like below which is not a valid json.
[
"OrderNumber": 01869756,
"customer_key": SLApO64gAktgmuLl,
"order_address": {\"address\":\"No. 7 Ogwui Road Enugu\",\"city\": \"Enugu\"};
"order_amount": 242550,
"order_currency": &#8358,
"order_currency_iso: NGN,
"order_shipping" = 0;
"order_stores": {
zOEZPU8sGCADHRbr8yw4 = {
amount = 242550;
currency = "₦";
delivery = 0;
total = 242550;
};
};
"order_subtotal": 242550,
"order_subtotal_cent: 24255000,
"order_tax": 4123.35,
"order_tax_cent": 412335,
"order_total": 246673.35",
"order_total_cent": 24667335,
"status" = 200
]
Since the type of message.body is __NSFrozenDictionaryM, you can turn it into a JSON string using JSONSerialization:
if let jsonData = try? JSONSerialization.data(withJSONObject: message.body, options: []) {
if let jsonString = String(data: jsonData, encoding: .utf8) {
print("dictFromJSON", jsonString)
}
}
If you want to see the JSON formatted prettily, pass .prettyPrinted to options:.
The JSONDecoder API does not work so well here as you are dealing with JSON in the form of a dictionary. JSONDecoder works best when you have Codable types.

Getting error when parsing JSON in Swift 3

1. This is the response String
{"error_msg": null,"applicationStateJson": {"notifications_size": "0","dfilterlogin": 1,"loginstype": null,"email_status": "0","address_status": "0","defaultfiltername": "hyderabad","login_status": "1","defaultfilterid": 145,"profile_id": null,"freelancer": "Y","otp_status": "1","notifications": []},"status": null}
2. Below one is the perfect JSONObject, I get it to using JSONLint
{
"error_msg": null,
"applicationStateJson": {
"notifications_size": "0",
"dfilterlogin": 1,
"loginstype": null,
"email_status": "0",
"address_status": "0",
"defaultfiltername": "hyderabad",
"login_status": "1",
"defaultfilterid": 145,
"profile_id": null,
"freelancer": "Y",
"otp_status": "1",
"notifications": []
},
"status": null
}
3. When I try the below code in Swift 3
let json1 = try? JSONSerialization.jsonObject(with: data, options: [])
if let object = json1 as? [String: Any]{
if let applicationState = object["applicationStateJson"] as? [String: Any]{
print("applicationState \(applicationState)")
}
}
4. I got JSONObject but it's not a proper JSONObject
(because the commas are changed into semicolon, null values are changed into "< null >" and then empty array [] changed into ())
Optional({
applicationStateJson = {
"address_status" = 0;
defaultfilterid = 145;
defaultfiltername = hyderabad;
dfilterlogin = 1;
"email_status" = 0;
freelancer = Y;
"login_status" = 1;
loginstype = "<null>";
notifications = (
);
"notifications_size" = 0;
"otp_status" = 1;
"profile_id" = "<null>";
};
"error_msg" = "<null>";
status = "<null>";
})
I want the JSONObject like the step 2, any help?
To read and use a JSON response in Swift does not require you to convert the JSON object back to JSON just to get a particular part. Once you have the data loaded into a Swift type you can work directly with it to get the parts you need.
So the long way which explains my point better...
let jsonData = jsonString.data(using: .utf8)!
let json1 = try? JSONSerialization.jsonObject(with: jsonData, options: [])
if let object = json1 as? [String: Any]{
if let applicationState = object["applicationStateJson"] as? [String: Any]{
print("applicationState \(applicationState)")
if let addressStatus = applicationState["address_status"] as? String {
print(addressStatus)
}
}
}
The Swift 4 way of doing this with the Codable Protocol
let jsonString = "{\"error_msg\": null,\"applicationStateJson\": {\"notifications_size\": \"0\",\"dfilterlogin\": 1,\"loginstype\": null,\"email_status\": \"0\",\"address_status\": \"0\",\"defaultfiltername\": \"hyderabad\",\"login_status\": \"1\",\"defaultfilterid\": 145,\"profile_id\": null,\"freelancer\": \"Y\",\"otp_status\": \"1\",\"notifications\": []},\"status\": null}"
struct ApplicationState: Codable {
let notificationsSize: String
let dFilterLogin: Int
let loginsType: String?
let emailStatus: String
let addressStatus: String
enum CodingKeys : String, CodingKey {
case notificationsSize = "notifications_size"
case dFilterLogin = "dfilterlogin"
case addressStatus = "address_status"
case loginsType = "loginstype"
case emailStatus = "email_status"
}
}
struct ApplicationStateResponse: Codable {
let errorMsg: String?
let applicationState: ApplicationState
enum CodingKeys : String, CodingKey {
case errorMsg = "error_msg"
case applicationState = "applicationStateJson"
}
}
let jsonData = jsonString.data(using: .utf8)!
let decoder = JSONDecoder()
let response = try! decoder.decode(ApplicationStateResponse.self, from: jsonData)
let appState = response.applicationState
print(appState.addressStatus)
Both of these print 0 for the address status as expected. one is much easier to work with than the other though.
This article which explains the codable protocol a bit more would be a good read.
Convert Swift Dictionary object to JSON string,
if let theJSONData = try? JSONSerialization.data(withJSONObject: applicationState, options: .prettyPrinted),
let theJSONText = String(data: theJSONData, encoding: String.Encoding.ascii) {
print("JSON string = \n\(theJSONText)")
}

Deserialize a Dictionary (JSON) to a swift object

I'm trying to build a login function (POST method) and the resultant is a JSON with user details and few other details. I have created a class with all the fields I need to use from the result of POST call. But I'm facing an issue with deserialzing the json to the object of the class. Can some one help me with this. (I have seen similar questions on SO and tried solving using the solution. I have tried converting the json to string and then to swift object using var UserDetails = UserDetails(json:jsonString)
)
My code:
class UserDetails {
let token:String
let agent_id: Int
let user_id:Int
let company_id:Int
let affliate_Id:Int
let role_id:Int
let username: String
let surname:String
let lastname:String
init(token:String,agent_id: Int,user_id:Int,company_id:Int,affliate_Id:Int,role_id:Int,username: String,surname:String,lastname:String) {
self.token = token;
self.agent_id = agent_id;
self.user_id = user_id;
self.company_id = company_id;
self.affliate_Id = affliate_Id;
self.role_id = role_id;
self.username = username;
self.surname = surname;
self.lastname = lastname;
} }
My controller class:
let task = session.dataTask(with: request as URLRequest) { data, response, error in
guard data != nil else {
print("no data found: \(error)")
return
}
do {
if let json = try JSONSerialization.jsonObject(with: data!, options: []) as? NSDictionary {
NSLog("Login SUCCESS");
let prefs:UserDefaults = UserDefaults.standard
prefs.set(username, forKey: "USERNAME")
prefs.set(udid, forKey: "UDID")
prefs.synchronize()
print("Response: \(json)")
//var jsonString = NSString(data: json, encoding: String.Encoding.utf8)! as String
//when I tried to do the above statement, an error is thrown. Cannot convert value of type NSDictionary to expected argument type Data
//var person:UserDetails = UserDetails(json: jsonString)
self.dismiss(animated: true, completion: nil)
} else {
let jsonStr = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)// No error thrown, but not NSDictionary
print("Error could not parse JSON: \(jsonStr)")
}
} catch let parseError {
print(parseError)// Log the error thrown by `JSONObjectWithData`
let jsonStr = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print("Error could not parse JSON: '\(jsonStr)'")
}
}
task.resume()
JSON Response:
{
"user": {
"token": "ABCDEFGHI",
"agent_id": 0,
"user_id": 151,
"company_id": 1,
"affiliate_Id": 0,
"role_id": 1,
"username": "testman1",
"surname": "Test",
"lastname": "man",
},
"menu": [
{ .....
Can someone help me in solving this. Tia
You should avoid using Foundation classes (NSDictionary etc) and use Swift types.
I also suggest you add a failable initialiser to your UserDetails class that accepts a dictionary:
class UserDetails {
let token: String
let agentId: Int
let userId: Int
let companyId: Int
let affliateId: Int
let roleId: Int
let username: String
let surname: String
let lastname: String
init?(dictionary: [String:Any]) {
guard let token = dictionary["token"] as? String,
let agentId = dictionary["agent_id"] as? Int,
let userId = dictionary["user_id"] as? Int,
... // And so on
else {
return nil
}
self.token = token;
self.agentId = agentId;
self.userId = userId;
self.companyId = companyId;
self.affliateId = affliateId;
self.roleId = roleId;
self.username = username;
self.surname = surname;
self.lastname = lastname;
}
}
and in your completion block:
do {
if let json = try JSONSerialization.jsonObject(with: data!, options: []) as? [String:Any] {
if let userDict = json["user"] as [String:Any] {
guard let userObject = UserDetails(dictionary:userDict) else {
print("Failed to create user from dictionary")
return
}
// Do something with userObject
}
}
} catch let parseError {
I also took the liberty of removing the _ from your properties because _ are icky
First of all you need to use Swift native Dictionary instead of NSDictionary also batter if you define your init method of UserDetails with single parameter of type [String: Any].
class UserDetails {
var token:String = ""
var agent_id: Int = 0
var user_id:Int = 0
var company_id:Int = 0
var affliate_Id:Int = 0
var role_id:Int = 0
var username: String = ""
var surname:String = ""
var lastname:String = ""
init(userDic: [String: Any]) {
if let token = user["token"] as? String, let agent_id = user["agent_id"] as? Int,
let user_id = user["user_id"] as? Int, let company_id = user["company_id"] as? Int,
let affliate_Id = user["affliate_Id"] as? Int, let role_id = user["role_id"] as? Int,
let username = user["username"] as? String, let surname = user["surname"] as? String,
let lastname = user["lastname"] as? String {
self.token = token;
self.agent_id = agent_id;
self.user_id = user_id;
self.company_id = company_id;
self.affliate_Id = affliate_Id;
self.role_id = role_id;
self.username = username;
self.surname = surname;
self.lastname = lastname;
}
}
}
Now simply call this init method from your json response like this.
if let json = try JSONSerialization.jsonObject(with: data!, options: []) as? [String: Any], let userDic = json["user"] as? [String: Any]{
let userDetails = UserDetails(userDic: userDic)
}

Parse nested elements in JSON

I couldn't seem to parse the following json:
["data": {
companies = (
);
"login_status" = success;
"rs_customer" = {
id = "<null>";
name = "<null>";
status = "<null>";
};
user = {
email = "email#email.com";
id = 0;
lastlogin = "06/14/16 12:44 am";
name = "Jayson Tamayo";
password = mypassword;
phone = "112345";
};
}, "status": success]
I retrieve that JSON thru:
HTTPGetJSON("http://myurl.com") {
(data: Dictionary<String, AnyObject>, error: String?) -> Void in
if error != nil {
print(error)
} else {
print(data)
let status = data["status"] as? String
print(status)
}
}
When I print the "status" it works. But when I try to use data["name"] I get nil. I also tried data["data"]["name"] but I also get nil.
Your main object is a dictionary.
In the "data" key, there's several values: "companies" is an array, "rs_customer" is a dictionary, the statuses are Strings and "user" is a dictionary.
So, to get the user, you would just have to cast to the proper types, something like this, if data is the object we see in the question:
if let content = data["data"] as? [String:AnyObject] {
if let user = content["user"] as? [String:AnyObject] {
if let name = user["name"] as? String {
print(name)
}
}
}
You can also chain the unwrapping for simpler code:
if let content = data["data"] as? [String:AnyObject],
user = content["user"] as? [String:AnyObject],
name = user["name"] as? String {
print(name)
}

How to parse JSON returned from a webservice in swift

Hey i am new to swift and I need to parse this JSON and get the value of "name" returned from a webservice:
{name = "Sameer Hussain";}
Here is my code so far:
var url: NSURL = NSURL(string: "http://xxxxxxxxx.com/xxxxx/xxxx.php")!
var request:NSMutableURLRequest = NSMutableURLRequest(URL:url)
var bodyData = "data=something"
request.HTTPMethod = "POST"
//request.HTTPBody = bodyData.dataUsingEncoding(NSUTF8StringEncoding);
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue())
{
(response, data, error) in
// println(data)
var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
//println(strData)
var err1: NSError?
var json2 = NSJSONSerialization.JSONObjectWithData(strData!.dataUsingEncoding(NSUTF8StringEncoding)!, options: .MutableLeaves, error:&err1 ) as! NSDictionary!
println("\(json2)")
}
From the code above it seems like your data is being saved within the json2 variable. To retrieve a value from that variable you can try something like this.
var userName: String?
var userAge: Int?
var userEmail: String?
if let parseJSON = json2
{
userName = parseJSON["name"] as? String
userAge = parseJSON["age"] as? Int
userEmail = parseJSON["email"] as? String
}
The above would work if your returned JSON looks something like this:
{
"name": "John"
"age": "21"
"email": "john#gmail.com"
}