Unable to Parse a JSON Object iOS Swift - ios

When I try to Parse a JSON object,
let json = try? JSONSerialization.jsonObject(with: reportData, options: []) as? [String : Any]
I get an error saying that
Cannot invoke 'jsonObject' with an argument list of type
'with:([String:Any]), options:[Any]'
Here is my reportData in JSON format, obtained from Server
{
"status": "success",
"statusCode": 200,
"message": "Report exists",
"patientReport": {
"caseId": "case040784",
"Observations": "These are test observations",
"userUid": "MY5FDbl0bgZStAY5Ky6OtYAzbDT2",
"nextSteps": "Here are my next steps",
"customerUid": "customerUid",
"results": {
"test1": "12",
"test3": "15",
"test3": "12"
}
}
}
Could someone please guide me where I am going wrong.

This function:
jsonObject(with: Data, options: JSONSerialization.ReadingOptions = [])
requires two parameters with type Data and JSONSerialization.ReadingOptions.
Your reportData is Dictionary not a Data. So you can use it without parse to Dictionary.

Cannot invoke 'jsonObject' with an argument list of type 'with:([String:Any]), options:[Any]'
I think this may be the strangest thing I've seen today.
Reading this message literally says that reportData is of type ([String: Any])—A tuple containing a single value [String: Any].
After reading Creating Tuples For a Single Value, I see there is no difference between ([String: Any]) and [String: Any].
The other users have already answered it… You don't need to parse the already dictionary object, I just found the tuple thing intresting.

Related

How to correctly send array with objects in JSON Swift iOS

Hello I am beginner and trying to understand how to send an array with objects. Does the server understand what an array is like Int, Strings or Booleans? Do you have to send the array in a string for JSON? What I do not understand?
var productsResult = ""
let encoder = JSONEncoder()
let productObject = ProductUsed(name: "Custom name", reason: "This Reason", apply_way: "Intravenous infusion", dosing: "2x", date_start: "22-02-1999", date_end: "22-03-2003")
do {
let result = try encoder.encode([productObject])
if let resultString = String(data: result, encoding: .utf8) {
print(resultString)
productsResult = resultString
}
} catch {
print(error)
}
json["products_used"] = productsResult
And I sent to server with parameters like this:
parameters: ["pregnancy_week": 0, "body_height": 198, "initials": "John Appleseed", "heavy_effect": false, "sex": "Male", "pregnancy": false, "month_of_birth": 3, "reaction": "No option checked", "additional_info": "Eeee", "products_used": "[{\"date_end\":\"22-03-2003\",\"dosing\":\"2x\",\"date_start\":\"22-02-1999\",\"apply_way\":\"Intravenous infusion\",\"name\":\"Custom name\",\"reason\":\"This Reason\"}]", "description": "Eeee", "result": "Recovery without lasting consequences", "year_of_birth": 1983, "day_of_birth": 11, "issue_date": "15-11-2020", "body_weight": 78]
but printed "resultString" in log and looks good...
[{"date_end":"22-03-2003","dosing":"2x","date_start":"22-02-1999","apply_way":"Intravenous infusion","name":"Custom name","reason":"This Reason"}]
What's wrong in my code and why I have " \ " between words in "products_used" key?
JSON, unlike XML, does not specify the structure and type explicitly. This means that the server must know what JSON data to expect.
In JSON there are a few value types (https://www.w3schools.com/js/js_json_syntax.asp):
a string
a number
an array
a boolean
null
a JSON object (a dictionary with tags like { "first" : "John", "last" : "Doe" }). This allows nesting.
A JSON object is a set of tag-value pairs. The tag and value are separated by : and pairs are separated by ,.
An array is a list of JSON values. So for example [ "hello", world" ] is a JSON array with 2 strings and [ 12, 54 ] is a JSON array with two numbers.
Your parameter list ["pregnancy_week": 0, "body_height": 198, ... is not an array but a dictionary instead. A Swift dictionary is translated to an JSON object, not a JSON array.
The \ you see printed acts as escape character. This escape character is used to allow you to have a " inside the string.
That's just a few things that I hope will help understand things a bit better. Your questions are pretty basic, which is fine and it's great you want to understand things. But instead of us explaining everything here, I think it would be best if you'd read about the structure of JSON and how JSON works in Swift on your own.

Assigning a dictionary of type [String:AnyObject] to [String: String] gives nil error

Hey I am newbie in Swift & IOS development. I am facing an issue searched a lot. But didn't got any solution.
I have dictionary of type [String: AnyObject] and wants to assign it to an other dictionary of type [String:String]. Xcode Shows an error which is this "Fatal error: Unexpectedly found nil while unwrapping an Optional val"
I tripled checked there is no nil value. Below here is my code snippet
Dictionary is here
let dictFormData = ["name": endorsement.name,
"designation":endorsement.designation,
"location": endorsement.location,
"region": endorsement.region,
"effectiveDateString":endorsement.effectiveDate,
"marriageDateString": "ss" ,
"genderId": String(format: "%ld", selectedGenderLookUpId),
"relationId": String(format: "%ld", selectedRelationLookUpId),
"plan": "ss",
"employeeId": AICLPolicyModel.getSelectedPolicy()?.employeeID as Any,
"requestTypeId": 35,
"policyId": AICLPolicyModel.getSelectedPolicy()?.policyID as Any,
"isEmployee": isemployee,
"filePath":"ss",
"fileName": "ss",
"empRemarks": endorsement.remarks,
"hrRemarks": "ss",
"adminRemarks": "ss",
"memberCode": AICLPolicyModel.getSelectedPolicy()?.memberCode as Any,
"requestStatusId": 32,
"customerId": AICLPolicyModel.getSelectedPolicy()?.clientID as Any
]
Here is assigning of one dictionary to other.
let formData = (dictFormData as? [String : String])!
At this line it shows error once again I am quite sure there is no nil value.
A dictionary of type [String:AnyObject] cannot be downcast to [String:String] since the types are incompatible.
Therefore dictFormData as? [String:String] evaluates to nil because the conditional downcast fails - you are then force unwrapping this nil with ! and you get a crash.
You are clearly putting non-String values into dictFormData, so you won't be able to use a simple downcast to get a [String:String] dictionary.

Parse Dictionary of Array of Dictionary in Swift 3

I am working on a project where I am getting a dictionary of an array which again containt the dictionary
My Json Response is
{
"code": 200,
"status": "OK",
"success": "true",
"message": "success",
"data": {
"vehicletypeData": [
{
"vehicle_type_id": "1",
"vehicle_type": "Any"
},
{
"vehicle_type_id": "11",
"vehicle_type": "Bike"
}
]
}
}
And I am parsing the data like
if response.success {
let resObj = response.responseObject as! Dictionary<String, Any>
let catArray = resObj["data"] as! Dictionary<String,Array<Dictionary<String,Any>>> // Crashes here
let vehicleData = catArray["vehicletypeData"] as! Array<Dictionary<String, Any>>
for vehicle in vehicleData {
self.jobCategories.append(PreJobVehicleData.mj_object(withKeyValues: vehicle))
}
}
I am trying to parse it in my model
Here I am getting an error like
- Could not cast value of type '__NSArrayM' (0x109b82e00) to 'NSDictionary' (0x109b832d8)
Any help will be Thankful.
Don't say
resObj["data"] as! Dictionary<String,Array<Dictionary<String,Any>>>
That's too specific. Just say
resObj["data"] as! [String:Any]
You know that when you get something by key out of that dictionary, it will be an array, but you can literally cross that bridge when you come to it.
The same rule applies to your other casts. Just cast to Swift dictionary or array using the broadest simplest possible type.
(Note that all this will be solved in Swift 4, where you can build a knowledge of the JSON structure right into your fetch.)
As you are parsing the nodes separately anyway avoid to cast to (more than two levels) nested types.
According to the error message the value for key data seems to be an array (Array<Dictionary<String, Any>>)
if response.success {
let resObj = response.responseObject as! Dictionary<String, Any>
let dataArray = resObj["data"] as! Array<Dictionary<String, Any>>
...
That implies however that the JSON output is wrong and I have no idea what's next...

Swift Dictionary adding square brackets after key for a value of type [String]

I have a serializer method that turns my swift objects into dictionaries so that I can send them in http requests.
this particular method is the one giving me the problem
class func toDictionary ( _ order: Order ) -> Dictionary<String, Any> {
return [
"products" : NSArray(array:order.getProducts()),
"owning_user" : NSString(string: order.getOwningUser()),
"restaurant" : NSString(string: order.getRestaurantId())
]
}
order.getProducts() returns an array of type [String]
When I send this in a http request it gets sent as
{"products[]":["...","..."],
"restaurant":"sdfsdf"
}
Obviously my server is expecting products as the key therefore its not getting the proper values.
Any idea why the square brackets are being added?
Note:
My http requests are done via alamofire
EDIT:
Turns out the problem was with alamofire
Please see below for solution
Turns out this is a problem to do with alamofire's encoding when passing a dictionary as a httpBody.
For anyone having the same problem:
solve this by adding the following property to your Alamofire post request
encoing: JSONEncoding.default
the final request looks as follows
Alamofire.request( requestURL, method: .post, parameters: orderJson, encoding: JSONEncoding.default)
and it yields the following JSON being posted
{ restaurant: '580e33ee65b84973ffbc7beb',
products: [ '580f5cdafaa1067e55be696d' ],
owning_user: '580e2d174e93b0734e9a04cb'
}
As I had originally wanted.
Ok this appears to work here, so I think I need more context as to what your doing different. If this solves your issue, please up vote! Thanks!
Possible issues; you may be have an array within another array? If order.getProducts() already returns an array, don't place it in another. Another option may be to .flatMap it "NSArray(array:order.getProducts()).flatMap {$0}" << will make a single array out of arrays of arrays.
//: Playground - noun: a place where people can play
import UIKit
func toDictionary () -> Dictionary<String, Any> {
return [
"products" : NSArray(array:["Paper","Pencil","Eraser"]),
"owning_user" : NSString(string: "user2976358"),
"restaurant" : NSString(string: "TacoBell")
]
}
let rValue = toDictionary()
let jsonData:Data!
do {
jsonData = try JSONSerialization.data(withJSONObject: rValue, options: .prettyPrinted)
let newString = String(data: jsonData, encoding: .utf8)
print(newString!)
} catch
{
print(error)
}
The results in the Debug area show this
{
"restaurant" : "TacoBell",
"products" : [
"Paper",
"Pencil",
"Eraser"
],
"owning_user" : "user2976358"
}

swift 3, JSON, invalid top-level type when writing

I have two exactly json objects, one is created from a function, the other is hard-coded, the hardcoded one works, the other doesn't (it always complains about the error invalid top-level type , which is weird. Any tip? Tks
let myData = self.dailyMileage?.toDictionary()
let directData = ["orgId" : self.orgId, "driverId" : self.driverId, "date" : Utils.getTodaysDate() ] as [String : Any]
//this won't work unless I substitute myData with directData
let jsonData = try JSONSerialization.data(withJSONObject: myData, options: .prettyPrinted)
//this is the function that produces myData, and nothing is nil
public func toDictionary() -> [String : Any] {
let dict = [ "orgId" : orgId , "driverId": driverId, "date" : date] as [String : Any]
return dict
}
JSONSerialization as given in the documentation:
An object that may be converted to JSON must have the following properties:
The top level object is an NSArray or NSDictionary. All objects are instances of NSString, NSNumber, NSArray, NSDictionary, or NSNull.
All dictionary keys are instances of NSString. Numbers are not NaN or infinity.
Other rules may apply. Calling isValidJSONObject(_:) or attempting a conversion are the definitive ways to tell if a given object can be converted to JSON data.
I think the one that's coming from the function might have an NSDate object instead of an NSString object.
The other reason is because your myData object is optional. JSONSerialization may give an error like that is the object is optional.
Please check if it is due to one of those two reasons. Feel free to suggest edits to make it better.

Resources