Parse data from socket.io response swift - ios

I have response from socket io library with response like this
socket.on("response-names") { data, ack in
print(data)
}
can print this,
[{
"person": [{
"_id":"56512323212132",
"name":"John Smith",
"id":"0000001",
"geolocation":{
"latitude":5.12312323443,
"longitude":101.12312464564354
}
}]
}]
How do you guys access the name, id and the geolocation(lat, long) in swift ?,
As far as I know the data is NSArray. but accessing is with data[0] will produce nil. but i can do data.count which will return with 1.
Thank you

Finally i solved it, just for future reference for others. It looks like you need to know the type before you parsing it. and check it with print.
and the debug code really helping, something like NSCFArray means your data as NSArray and try to read from that.
let dataArray = data as NSArray
let dataString = dataArray[0] as! String
let dataNewNow = dataString.data(using: String.Encoding.utf8, allowLossyConversion: false)!
do {
let json = try NSJSONSerialization.JSONObjectWithData(dataNewNow, options: []) as! [String: AnyObject]
let str = json["person"] as! NSArray
let str2 = str[0] as! NSDictionary
let personName = str2["name"] as! String
let personId = str2["id"] as! String
let personGeoLocation = str2["geolocation"] as! NSDictionary
let personLatitude = personGeoLocation["latitude"] as! NSNumber
let personLongitude = personGeoLocation["longitude"] as! NSNumber
print("personName =", personName)
print("personID =", personId)
print("Person Latitude =", personLatitude)
print("Person Longitude =", personLongitude)
} catch let error as NSError {
print("Failed to load: \(error.localizedDescription)")
}

in my case this worked
let dataArray = data as NSArray
let dataString = dataArray[0] as! String
let dataNewNow = dataString.data(using: String.Encoding.utf8, allowLossyConversion: false)!
do {
let json = try JSONSerialization.jsonObject(with: dataNewNow, options: []) as! [String: AnyObject]
let nMsgType = json["msg_type"] as! String
print(nMsgType)
} catch let error as NSError {
print("Failed to load: \(error.localizedDescription)")
}

I know it's a very old question but my answer may help someone ... In today's swift 5 it's very easy than before...
Create a SocketParser and use the below code to parse data...
class SocketParser {
static func convert<T: Decodable>(data: Any) throws -> T {
let jsonData = try JSONSerialization.data(withJSONObject: data)
let decoder = JSONDecoder()
do{
let _ = try decoder.decode(T.self, from: jsonData)
}catch{
createLog("CheckError \(error)")
}
return try decoder.decode(T.self, from: jsonData)
}
}
Now Create a simple model for your JSON ... in you case as bellow...
import Foundation
// MARK: - WelcomeElement
struct WelcomeElement: Codable {
let person: [Person]
}
// MARK: - Person
struct Person: Codable {
let id, name, personID: String
let geolocation: Geolocation
enum CodingKeys: String, CodingKey {
case id = "_id"
case name
case personID = "id"
case geolocation
}
}
// MARK: - Geolocation
struct Geolocation: Codable {
let latitude, longitude: Double
}
It's time to use these in response as below...
socket.on("response-names") { data, ack in
guard let data = data.first else{
return
}
if let response : WelcomeElement = try? SocketParser.convert(data: data) {
print(responce)
}

Related

need to get the country name from open api

Needs to get country name from below api call :
https://restcountries.eu/rest/v1/all
My code :
var arrRes = []
func getCountry() {
let Url: String = "https://restcountries.eu/rest/v1/all"
Alamofire.request(Url).responseJSON { (responseData) -> Void in
do {
if let datas = responseData.result.value {
let data = (datas as AnyObject).data(using: .utf8)!
let parseData = try JSONSerialization.jsonObject(with: data, options: [])
for country in parseData {
if let name = country["name"] as? String {
print(name)
}
}
}
}
catch let error as NSError {
print(error)
}
}
}
getting error here : 'Any' is not convertible to 'AnyObject' on below line let data = (datas as AnyObject).data(using: .utf8)!..
I need to get only name and append to my array.Any other idea or solution to achieve that ?
Replace do catch block of statement with this.
do {
if let countries = responseData.result.value as? [[String: Any]] {
for country in countries {
if let name = country["name"] as? String {
print(name)
}
}
}
}
catch let error as NSError {
print(error)
}
Try this, its working fine for me.
let urlStr = "https://restcountries.eu/rest/v1/all"
let setFinalURl = urlStr.addingPercentEncoding (withAllowedCharacters: .urlQueryAllowed)!
var request = URLRequest(url: URL(string: setFinalURl)!)
request.httpMethod = HTTPMethod.get.rawValue
Alamofire.request(request).responseJSON
{ (responseObject) -> Void in
if responseObject.result.isSuccess
{
print(responseObject.result.value!)
if "\(String(describing: responseObject.response!.statusCode))" == "200"
{
let result = responseObject.result.value! as AnyObject
let countryNamesArr = result.value(forKey: "name") as! NSArray
print(countryNamesArr)
}
else
{
// handle error
}
}
if responseObject.result.isFailure
{
let error : Error = responseObject.result.error!
print(error.localizedDescription)
}
}
You can try
struct Root: Codable {
let name: String
}
func getCountry() {
let urlStr = "https://restcountries.eu/rest/v1/all"
Alamofire.request(urlStr).responseData { (data) in
do {
guard let data = data.data else { return }
let res = try JSONDecoder().decode([Root].self,from:data)
print(res)
}
catch {
print(error)
}
}
}
Just remove this line
let data = (datas as AnyObject).data(using: .utf8)!
and in optional binding just assign data, since value is of type Data?, from optional binding you get Data
if let data = responseData.result.value
then don't forget to downcast your json to array [String:Any]
...jsonObject(with: data, options: []) as? [[String:Any]]
... then don't forget to unwrap this array or you wouldn't be able to iterate through it in for each loop
Also note that since there is Codable, you should use it instead of JSONSerialization. Then you can decode your json using JSONDecoder to your own model which conforms to protocol Decodable.
As a simple approach, you could implement getCountry() like this:
func getCountry() {
let url: String = "https://restcountries.eu/rest/v1/all"
Alamofire.request(url).responseJSON { response in
if let resultValue = response.result.value, let countryObjects = resultValue as? [[String: Any]] {
let countryNames = countryObjects.compactMap { $0["name"] as? String }
print(countryNames)
}
}
}
At this point, there is no need to use JSONSerialization to get the country names; According to the API response, responseData.result.value is an array of countries (dictionaries), each dictionary has a "name" value, what you should do is to map the response to an array of string. countryNames should contains what are you looking for.
The benefit of using compactMap is to avoid any nil name, so countryNames should be [String] instead of [String?].
However, if you believe that you would need to transform the whole response objects into a custom objects (instead of dictionaries), I would highly recommend to follow the approach of using Decodable.
My code, its working well for me.
Swift 5
public func getCountry(completion: #escaping ([String]) -> ()) {
let url: String = "https://restcountries.eu/rest/v1/all"
AF.request(url).responseJSON { (responseData) -> Void in
do {
guard let data = responseData.data else { return }
let res = try JSONDecoder().decode([CountryName].self,from:data)
completion(self.getCountryName(countryName: res))
}
catch {
print(error)
}
}
}
struct CountryName: Codable {
let name: String
}
private func getCountryName(countryName:[CountryName]) -> [String]{
var country:[String] = []
for index in 0...countryName.count - 1{
country.append(countryName[index].name)
}
return country
}

I try to convert Json string (response) to json object but after JSONSerialization the output is not clear

I got a response from web service and try to work on it to put it in a model, but i can't work with it .
this is the response.string
"{\"USER_NO\":1,\"USER_NAME\":\"المسار البديل لتكنولوجيا المعلومات\",\"TASK_CATEGORY_NO\":1,\"USER_ID_NUMBER\":\"1031523473\",\"Mobile_No\":\"0567123432\"}"
I used extension :
extension String{
func tooDictionary() -> NSDictionary {
let blankDict : NSDictionary = [:]
if let data = self.data(using: .utf8) {
do {
return try JSONSerialization.jsonObject(with: data, options: []) as! NSDictionary
} catch {
print(error.localizedDescription)
}
}
return blankDict
}
}
to convert it to dictionary then put it in object but i failed to do that
i'm sorry but i'm new developer in swift4 ,any help please
and thank
Use Decodable:
struct User: Decodable {
private enum CodingKeys : String, CodingKey {
case userNumber = "USER_NO", taskCategoryNumber = "TASK_CATEGORY_NO"
case userName = "USER_NAME", userID = "USER_ID_NUMBER", mobileNumber = "Mobile_No"
}
let userNumber, taskCategoryNumber: Int
let userName, userID, mobileNumber : String
}
let jsonString = """
{"USER_NO":1,"USER_NAME":"المسار البديل لتكنولوجيا المعلومات","TASK_CATEGORY_NO":1,"USER_ID_NUMBER":"1031523473","Mobile_No":"0567123432"}
"""
let data = Data(jsonString.utf8)
do {
let result = try JSONDecoder().decode(User.self, from: data)
print(result)
} catch { print(error) }
Note: Don't use NSArray / NSDictionary in Swift

Get JSON data from NSDictionary

I have struct in my api
{
"Hall":"Hall",
"Date":20180501,
"Prices":[
{
"Time":1,
"Price":4000
},
{
"Time":2,
"Price":4000
},
{
"Time":3,
"Price":4000
}
]
}
Now I'm stuck and can't pull out the price and time. I understand that there were many question, but I still can't understand, please help.
I use this code:
let url = URL(string: "http://<...>/api/prices?hall=<...>&date=20180501")
var request = URLRequest(url: url!)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(with: request, completionHandler: { (data, response, error) in
if let err = error {
print(err)
} else {
do {
if let jsonResult = try JSONSerialization.jsonObject(with: data!, options: []) as? NSDictionary {
// ...
}
DispatchQueue.main.async {
self.collectionView.reloadData()
}
} catch {
print("error")
}
}
})
task.resume()
}
I'm new with json, and just started learning it. I know it's easy, but I can't figure it out. I also know that i can use codable and decodable, but now I need to get price and time in this implementation.
First of all don't use NSArray / NSDictionary, use native Swift types.
The value for key Prices is an array of [String:Int] dictionaries:
if let jsonResult = try JSONSerialization.jsonObject(with: data!) as? [String:Any],
let prices = jsonResult["Prices"] as? [[String:Int]] {
for price in prices {
print(price["Time"]!, price["Price"]!)
}
}
However I would recommended to decode the JSON into a struct which is very simple in Swift 4
struct Item : Decodable {
let hall : String
let date : Int
let prices : [Price]
private enum CodingKeys : String, CodingKey { case hall = "Hall", date = "Date", prices = "Prices"}
}
struct Price : Decodable {
let time, price : Int
private enum CodingKeys : String, CodingKey { case time = "Time", price = "Price"}
}
do {
let result = try JSONDecoder().decode(Item.self, from: data!)
print(result)
} catch { print(error) }
Product Structure:
struct Product{
let time:Int
let price:Int
init(_ object:[String:Int]){
self.time = object["Time"] ?? 0
self.price = object["Price"] ?? 0
}
}
Class Variable:
var products = [Product]()
JSON parsing:
do{
if let jsonObject = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:Any] {
//Use Swift dictionary instead of NSDictionary
if let prices = jsonObject["Prices"] as? [[String:Int]]{
for price in prices{
self.products.append(Product(price))
}
}
}
}catch{
print("Error: ",error.localizedDescription)
}
Now, your products Array will contain all Price and Time
Example:
for product in products{
print("Time:",product.time)
print("Price:",product.price)
}
Output:
Time: 1
Price: 4000
Time: 2
Price: 4000
Time: 3
Price: 4000
Note: For better understanding, this is my video series about JSON parsing in swift 4
var timeArray = [String]()
var priceArray = [String]()
if jsonResult.object(forKey:"Prices") as? NSArray != nil
{
let pricesArray = jsonResult.object(forKey:"Prices") as! NSArray
for i in 0..<self.pricesArray.count
{
// Getting Time
if jsonResult.object(forKey:"Time") as? Int != nil
{
self.timeArray.append(jsonResult.object(forKey:"Time") as! Int)
}
else
{
print("Time is not a intrger")
}
// Getting Price
if jsonResult.object(forKey:"Price") as? Int != nil
{
self.priceArray.append(jsonResult.object(forKey:"Price") as! Int)
}
else
{
print("Price is not a intrger")
}
}
}
else
{
print("Empty Array")
}
if let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:Any], let pirces = json["prices"] // checking json is formed well.
{
for price in prices { // iterating throught array that you received.
print (price["Price"])
}
}

Issue in Parsing JSON object from CoreData

I converted a JSON object to string and stored it to CoreData. But how to parse the individual elements and get each of the elements after retrieving the JSON object that I'm not able to figure out....
This is how I'm getting the json object:
let mobileNumber = mobileNumberTextfield.text
let firstName = firstNameTextField.text
let jsonObject: [String: [String:Any]] = [
"user1": [
"mobile_number": mobileNumber,
"first_Name": firstName,
]
]
I'm printing JSON string like so...
if let data = try? JSONSerialization.data(withJSONObject: jsonObject, options: .prettyPrinted),
let str = String(data: data, encoding: .utf8) {
print(str)
}
printing str gives:
{
"user1" : {
"mobile_number" : "567567567",
"first_Name" : "iopiopi",
}
}
I'm storing it as it is to coredata and so when I retrive it I get it back in the very same format as above. But how can I retrieve the individual elements for later use that I can't figure out.
If I fetch it something like so...
for result in newProductDetails {
if let prodID = result.value(forKey: "address") as? String {
print(prodID)
}
}
and do a for (key, value) in addDetails.enumerated() & print value, it give this..
data: {
address = "{
\n \"user1\" : {
\n \"mobile_number\" : \"1236594525\",
\n \"first_Name\" : \"ghj\"
\n
}
\n
}";
})
But how can I extract individual values of mobile_number & first_Namefrom it ...?
You are storing the data (NSData obtained from the string encoding the JSON) and getting back that same data from CoreData. That means you have to parse the JSON in that NSData instance again. The round trip to JSON/NSData and back makes little sense. You probably just want to create an User entity and store the mobile number and first name into CoreData directly.
Convert Json string to Dictionary:
func convertToDictionary(text: String) -> [String: Any]? {
if let data = text.data(using: .utf8) {
do {
return try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
} catch {
print(error.localizedDescription)
}
}
return nil
}
let str = "{\"name\":\"James\"}"
let dict = convertToDictionary(text: str)
You should save like this in CoreData:
if let reposArray: AnyObject = json["user1"] as? NSDictionary {
self.mbleNo = reposArray["mobile_number"] as? String
let appDelegate = UIApplication.shared.delegate as! AppDelegate
if #available(iOS 10.0, *) {
let managedObjectContext = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Fields")
let entityDescription = NSEntityDescription.entity(forEntityName: "Fields", in:managedObjectContext)
let titleInfo = NSManagedObject(entity: entityDescription!, insertInto: managedObjectContext) as? Fields
titleInfo?.setValue(self.mbleNo, forKey: "mobile_number")
do {
try titleInfo?.managedObjectContext?.save()
}
catch {
print(error)
}
}
}

Convert Json string to Json object in Swift 4

I try to convert JSON string to a JSON object but after JSONSerialization the output is nil in JSON.
Response String:
[{\"form_id\":3465,\"canonical_name\":\"df_SAWERQ\",\"form_name\":\"Activity 4 with Images\",\"form_desc\":null}]
I try to convert this string with my code below:
let jsonString = response.result.value
let data: Data? = jsonString?.data(using: .utf8)
let json = (try? JSONSerialization.jsonObject(with: data, options: [])) as? [String:AnyObject]
print(json ?? "Empty Data")
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]]
Using JSONSerialization always felt unSwifty and unwieldy, but it is even more so with the arrival of Codable in Swift 4. If you wield a [String:Any] in front of a simple struct it will ... hurt. Check out this in a Playground:
import Cocoa
let data = "[{\"form_id\":3465,\"canonical_name\":\"df_SAWERQ\",\"form_name\":\"Activity 4 with Images\",\"form_desc\":null}]".data(using: .utf8)!
struct Form: Codable {
let id: Int
let name: String
let description: String?
private enum CodingKeys: String, CodingKey {
case id = "form_id"
case name = "form_name"
case description = "form_desc"
}
}
do {
let f = try JSONDecoder().decode([Form].self, from: data)
print(f)
print(f[0])
} catch {
print(error)
}
With minimal effort handling this will feel a whole lot more comfortable. And you are given a lot more information if your JSON does not parse properly.
I tried the solutions here, and as? [String:AnyObject] worked for me:
do{
if let json = stringToParse.data(using: String.Encoding.utf8){
if let jsonData = try JSONSerialization.jsonObject(with: json, options: .allowFragments) as? [String:AnyObject]{
let id = jsonData["id"] as! String
...
}
}
}catch {
print(error.localizedDescription)
}
I used below code and it's working fine for me. :
let jsonText = "{\"userName\":\"Bhavsang\"}"
var dictonary:NSDictionary?
if let data = jsonText.dataUsingEncoding(NSUTF8StringEncoding) {
do {
dictonary = try NSJSONSerialization.JSONObjectWithData(data, options: [.allowFragments]) as? [String:AnyObject]
if let myDictionary = dictonary
{
print(" User name is: \(myDictionary["userName"]!)")
}
} catch let error as NSError {
print(error)
}
}
static func getJSONStringFromObject(object: Any?) -> String? {
do {
let jsonData = try JSONSerialization.data(withJSONObject: object ?? DUMMY_STRING, options: [])
return String(data: jsonData, encoding: .utf8) ?? DUMMY_STRING
} catch {
print(error.localizedDescription)
}
return DUMMY_STRING
}

Resources