Parser to json JSON array using swift - ios

I am doing an IOS (swift) app that communicates with a server.
Response from server is a JSON array which contains some JSON objects.
When i show by console string response is fine:
[{"NAME":"","SURNAME":"","ID":5,"USERNAME":"dpcabo2"},{"NAME":"","SURNAME":"","ID":10,"USERNAME":"default"},{"NAME":"","SURNAME":"","ID":11,"USERNAME":"esteban"}]
But when i try parser this info to json using this:
var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(self.my_data!,
options:NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
println("\(jsonResult)")
app crashes.
So i need a solution to parser correctly this information.
Ps.self.my_data! is a NSMutableData.
Thanks

You can use below code for parsing. It prints and parse you object properly.
import Foundation
let jsonObject: [AnyObject] = [
["NAME":"","SURNAME":"","ID":5,"USERNAME":"dpcabo2"],
["NAME":"","SURNAME":"","ID":10,"USERNAME":"default"],
["NAME":"","SURNAME":"","ID":11,"USERNAME":"esteban"]
]
let jsonOptional: AnyObject! = NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions(0), error: nil)
Response is as below:
[["USERNAME": "dpcabo2", "ID": 5, "NAME": "", "SURNAME": ""],
["USERNAME": "default", "ID": 10, "NAME": "", "SURNAME": ""],
["USERNAME": "esteban", "ID": 11, "NAME": "", "SURNAME": ""]]

Related

JSONDecoder can't decode Array but can decode String

I have a struct that I would like to parse from Json:
struct Subsidiary: Decodable {
let id: Int?
let subsidiary_ref: String?
let name: String?
let address: String?
}
I try to parse it like:
let sub: [Subsidiary] = try! JSONDecoder().decode([Subsidiary].self, from: data)
where data is Data type from
session.dataTask(with: urlRequest) { (data, response, error) in
and it gives me an error
Fatal error: 'try!' expression unexpectedly raised an error: Swift.DecodingError.typeMismatch(Swift.Array<Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Array<Any> but found a string/data instead.", underlyingError: nil))
If I do it like this:
let sub: String = try! JSONDecoder().decode(String.self, from: data)
it works and it gives me son
[
{"id": 5913, "subsidiary_ref": "0000159", "name": "Mercator Hipermarket Koper", "address": "Poslov.98-Koper,Dolinska C", "city": "Koper", "coordinates_x": null, "coordinates_y": null, "phone_number": "+386 56-636-800", "frequency": "A", "channel": "Food", "subchannel": "Hypermarket", "customer": 7, "day_planned": true, "badge_visible": true, "open_call": true, "number_of_planned": 13, "number_of_calls": 22, "last_call_day": 3, "notes": " notesi ki ne smejo nikoli zginiti bla marko bdsa"},
{"id": 5870, "subsidiary_ref": "0000773", "name": "Kompas Shop Pe Ferneti?i", "address": "Partizanska 150", "city": "Se?ana", "coordinates_x": null, "coordinates_y": null, "phone_number": "+386 57-380-636", "frequency": "A", "channel": "Food", "subchannel": "Supermarket", "customer": 17, "day_planned": true, "badge_visible": true, "open_call": true, "number_of_planned": 13, "number_of_calls": 1, "last_call_day": 1, "notes": null},...
]
What is wrong with my code?
EDIT:
I figure out, that if I create a string variable, and then convert this string value to data it works even with Subsidiary struct.
So something should be wrong with the data variable.
The fact that you can decode a String.self and get your JSON printed means that the root of the JSON is a string. The JSON you got, in text form, probably looks like this:
"[\r\n {\"id\": 5913, \"subsidiary_ref\": \"0000159\", \"name\": \"Mercator Hipermarket Koper\", \"address\": \"Poslov.98-Koper,Dolinska C\", \"city\": \"Koper\", \"coordinates_x\": null, \"coordinates_y\": null, \"phone_number\": \"+386 56-636-800\", \"frequency\": \"A\", \"channel\": \"Food\", \"subchannel\": \"Hypermarket\", \"customer\": 7, \"day_planned\": true, \"badge_visible\": true, \"open_call\": true, \"number_of_planned\": 13, \"number_of_calls\": 22, \"last_call_day\": 3, \"notes\": \" notesi ki ne smejo nikoli zginiti bla marko bdsa\"}\r\n]"
Note that the actual JSON you want is put in ""s, so all the special characters are escaped.
The web service has given the JSON in a very weird way...
To get the actual JSON data decoded, you need to get the string first, then turn the string into Data, then decode that Data again:
// nil handling omitted for brevity
let jsonString = try! JSONDecoder().decode(String.self, from: data)
let jsonData = jsonString.data(using: .utf8)!
let sub = try! JSONDecoder().decode([Subsidiary].self, from: jsonData)
Of course, the best solution is to fix the backend.

How to consume an API response with Swift

I am trying to make an API request to get an API response I am getting all the elements but I am facing braces issue I want a whole response and "order_devices" key, in {} braces but I am getting these in [] braces.
the array in which i am passing value,
var popUpArray :[[String:AnyObject]] = []
then on btn click i am saving values in dictionary
#IBAction func btnSave(_ sender: Any) {
let popupDict = (["quantity": Int(txtEnterQuantity.text!), "name": lblDeviceName.text,"id": deviceDict["id"], "region":1, "system_integrated":1 ])as! [String:AnyObject]
and then passing the same dictionary value as parameter
let passDict = [
"dealer_id":dropDownId!,
"client_id":dropDownId!,
"distributor_id":searchBarId!,
"emp_id":UserId,
"comments":CommentKey!,
"accepted_by":0,
"valid_from":strDate!,
"valid_upto": 0,
"order_devices":popupDict
] as [String : Any]
if Reachability.isConnectedToNetwork() {
showActivityIndicator()
Alamofire.request("http://13.232.230.41/IAC_CRM/public/api/createOrder", method: .post, parameters: passDict, encoding: JSONEncoding.default, headers: [:])
.responseJSON { (response) in
i am getting this response ,
[
"comments": "demo",
"dealer_id": 3,
"valid_from": "6-3-2019",
"distributor_id": 72,
"client_id": 3,
"accepted_by": 0,
"emp_id": 33,
"valid_upto": 0
"order_devices":
[
[
"id": 1,
"quantity": 10,
"region": 1,
"system_integrated": 1
]
,
[
"id": 2,
"quantity": 12,
"region": 1,
"system_integrated": 1
]
]
]
i want this response,
{ "dealer_id":"1", "client_id":"2", "distributor_id":"2",
"emp_id":"1", "comments":"IAC test device comments", "accepted_by":0,
"valid_from":"2019-01-24", "valid_upto":"1", "order_devices":[
{
"device_id":"1",
"quantity":"1", "region":1, "system_integrated":1
}
,
{
"device_id":"2",
"quantity":"1"
"region":1,
"system_integrated":1
}
] }
means i want whole response and "order_devices" key in "curly braces"{} .
There is nothing wrong with request or response, your are getting response what your API is returning, You should ask you backend developer Or Api Provider to Give you response in form of your requirement i mean proper formatted Right now its in form of Array.

Swift Create Json for API REST

I need create a json for send from a API REST:
{
"ownId": "seu_identificador_proprio",
"amount": {
"currency": "BRL",
"subtotals": {
"shipping": 1000
}
},
"items": [
{
"product": "Descrição do pedido",
"quantity": 1,
"detail": "Mais info...",
"price": 1000
}
],
"customer": {
"ownId": "seu_identificador_proprio_de_cliente",
"fullname": "Jose Silva",
"email": "nome#email.com",
"birthDate": "1988-12-30",
"taxDocument": {
"type": "CPF",
"number": "22222222222"
},
"phone": {
"countryCode": "55",
"areaCode": "11",
"number": "66778899"
},
"shippingAddress": {
"street": "Avenida Faria Lima",
"streetNumber": 2927,
"complement": 8,
"district": "Itaim",
"city": "Sao Paulo",
"state": "SP",
"country": "BRA",
"zipCode": "01234000"
}
}
}
I am confused with the creation..
I try begin with [NSObject:AnyObject]
var d1 : [NSObject:AnyObject] = ["ownId":"seu_identificador_proprio", "customer":""]
let dd1 = ["currency":"BRL"]
let dd2 = ["shipping":"1000"]
let arr = [d1]
let d = try! NSJSONSerialization.dataWithJSONObject(arr, options: NSJSONWritingOptions.PrettyPrinted)
let s = NSString(data: d, encoding: NSUTF8StringEncoding)! as String
print(s)
But I need help!
I have updated your code and added some hints, how can you build the above listed structure. Happy coding!
// Do not use NSObject as key's type
// Keys in a dictionary are usually Strig in every language
var d1: [String: AnyObject] = ["ownId":"seu_identificador_proprio", "customer":""]
// Define the type of your dictionaries, if you dont, in this case it will create a [String:String] dictionary, but you need to insert an array into it
// Make it a var, so you can mutate the container
var dd1: [String: AnyObject] = ["currency":"BRL"]
// Here the type is undefined. Try inserting anything else than String, and see the results
let dd2 = ["shipping":"1000"]
dd1["subtotals"] = dd2
d1["amount"] = dd1
// Build all your dictionaries like i did above, and at the end add all of them into arr
let arr = [d1]
// Do not force try any throwing function in swift - if there is an error, your application will crash
// Use proper error handling - https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/ErrorHandling.html
do {
let d = try NSJSONSerialization.dataWithJSONObject(arr, options: NSJSONWritingOptions.PrettyPrinted)
let s = NSString(data: d, encoding: NSUTF8StringEncoding)! as String
print(s)
} catch {
// Do your error handling here
}

How to create this JSON Object in Swift

I have this JSON file which I want to create and send to a server. I am new to using JSON so please can someone guide me how can I create this Object ?
{
"today_steps": 5663,
"activities": [{
"activity_name": "Walking",
"start_datetime": "2016-07-03 10:03AM",
"activity_duration": 2768000,
"steps": 1362,
"average_heart": 96,
"calories": 109
}, {
"activity_name": "Running",
"start_datetime": "2016-07-03 02:45PM",
"activity_duration": 1768000,
"steps": 2013,
"average_heart": 112,
"calories": 271
}],
"workout": []
}
Try code
Swift 2
let activities = [["activity_name":"Walking",
"start_datetime":"2016-07-03 10:03AM",
"activity_duration":2768000,
"steps":1362,
"average_heart":96,
"calories":109],
["activity_name":"Running",
"start_datetime":"2016-07-03 02:45PM",
"activity_duration":1768000,
"steps":2013,
"average_heart":112,
"calories":271]]
let dictionary = ["today_steps":5663,
"activities":activities,
"workout":[]
]
print(dictionary)
do {
let jsonData = try NSJSONSerialization.dataWithJSONObject(dictionary, options: NSJSONWritingOptions.PrettyPrinted)
// here "jsonData" is the dictionary encoded in JSON data
} catch let error as NSError {
print(error)
}
Swift3
change convert dictionary to Json by
let jsonData = try JSONSerialization.data(withJSONObject: dictionary, options: .prettyPrinted)
You don't always need to create an object to send it to server. You can also create a request with the required headers and you can send it as a string.
Take a look at this library and its documentation.
https://github.com/Alamofire/Alamofire
You can also send NSDictionary and this library will convert that to a JSON object.
An example from their github.
let parameters = [
"foo": [1,2,3],
"bar": [
"baz": "qux"
] ]
Alamofire.request(.POST, "https://httpbin.org/post", parameters: parameters, encoding: .JSON)
// HTTP body: {"foo": [1, 2, 3], "bar": {"baz": "qux"}}
Try use this
let json = [
"today_steps": 5663,
"activities": [[
"activity_name": "Walking",
"start_datetime": "2016-07-03 10:03AM",
"activity_duration": 2768000,
"steps": 1362,
"average_heart": 96,
"calories": 109
], [
"activity_name": "Running",
"start_datetime": "2016-07-03 02:45PM",
"activity_duration": 1768000,
"steps": 2013,
"average_heart": 112,
"calories": 271
]],
"workout": []
]
You can go ahead and use the NSJSONSerialization class to convert the data to an object that can be later be parsed.
A method like the following can always be used.
// Given raw JSON, return a usable Foundation object
private func convertDataWithCompletionHandler(data: NSData, completionHandlerForConvertData: (result: AnyObject!, error: NSError?) -> Void) {
var parsedResult: AnyObject!
do {
parsedResult = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments)
} catch {
let userInfo = [NSLocalizedDescriptionKey : "Could not parse the data as JSON: '\(data)'"]
completionHandlerForConvertData(result: nil, error: NSError(domain: "convertDataWithCompletionHandler", code: 1, userInfo: userInfo))
}
completionHandlerForConvertData(result: parsedResult, error: nil)
}
Pass the JSON result given by the api call to this method.

Posting complex array with Alamofire

I have a problem with posting complex dynamic array with Alamofire to my REST API. I would like to post something like this;
let parameters = [
"A": "a",
"B": myObject.getStringValue(),
"C": myDate.timeIntervalSince1970,
"D": myObject2.getStringValue(),
"E": MyComplexData
];
Alamofire.request(.POST, "http://myrestapi.com/myaction", parameters: parameters);
Where the myComplexData is an array-like variable, which I would like to fill with a loop. I want receive data in the server like this:
[
"A": "a",
"B": "b",
"C": 24916942128,
"D": "d",
"E": [0: [ id: "firstID", value: "firstValue" ], 1: [ id: "secondID", value: "secondValue" ]]
]
My question is, how can I create a dynamic array (or dictionary?) into the MyComplexData to receive data like this?
Thanks in advance,
Robert
Finally, based on #Catalina T. answer, I did it with JSON encoded data. The full code:
var myComplexData = Dictionary<String, String>();
for i in previousCollectedDynamicDataArray {
myComplexData[i.getID()] = i.getVal();
}
let parameters = [
"A":"A",
"B": myObject.getStringValue(),
"C": myDate.timeIntervalSince1970,
"D": myObject2.getStringValue(),
"E": myComplexData
];
Alamofire.request(.POST, "http://myrestapi.com/myaction", parameters: [ "data": objToJSONString(parameters) ]);
And this is the objToJSONString function:
func objToJSONString(obj: AnyObject) -> String {
guard let data = try? NSJSONSerialization.dataWithJSONObject(obj, options: .PrettyPrinted),
let jsonString = NSString(data: data, encoding: NSUTF8StringEncoding)
else {
return "";
}
return jsonString as String;
}
And the server received the "data" post variable the JSON encoded data inside.

Resources