I'm having an issue getting a JSON array using Swift.
func getBenefitJSON() -> [AnyObject] {
let urlString = String("https://www.kyfb.com/KYFB/includes/themes/CodeBlue/display_objects/custom/remote/webservices/services.cfc?method=getMemberBenefits")
let url = URL(string: urlString!)
var data = Data()
do {
data = try Data(contentsOf: url!)
} catch {
}
print("URL Data: \(data)")
do {
let json = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions()) as! [AnyObject]
print("JSON: \(json)")
return json
} catch {
print("Could not get JSON")
return []
}
}
I get the data from the url but get an empty array returned. What am I doing wrong?
URL Data: 42769 bytes
Could not get JSON
Below is the response of JSON
[{"image":"https://cdn.kyfb.com/KYFB/cache/file/70162997-E06B-E9B6-88514280CA8397CC_medium.jpg","description":"","link":"https://www.kyfb.com/insurance/insurance-products/","name":"KFB Insurance","children":[]}, ...]
Below is the error
UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}
I've also validated the response from the URL at jsonlint.com
URL data as string:
<wddxPacket version='1.0'><header/><data><string>[{"image":"https://cdn.kyfb.com/KYFB/cache/file/70162997-E06B-E9B6-88514280CA8397CC_medium.jpg","description":"","link":"https://www.kyfb.com/insurance/insurance-products/","name":"KFB Insurance","children":[]}, ...]</string></data></wddxPacket>)
I tested your code and it is working if the top level of the JSON is an Array. So the JSON you want to read is probably not an array but a dictionary.
To read the Dictionary you need to change the return type from [AnyObject] into [String:AnyObject] and all other occurrences of this type.
Nevertheless, I would recommend to use SwiftyJSON for working with JSON in Swift.
Related
I have some objects which have Codable protocol so they coming from service API and turn into dictionaries. There are lots of Service function in the project so I can not fetch the the point where they turn into JSON or dictionary and I can not the see first state of these objects.
So is there any way so that i can see that dictionary values in console or somewhere else even if they had already become JSON ?
Thanks in advance.
You can use this extension to convert it from dictionary to JSON and by using it you can print it in the console.
extension Dictionary {
var json: String {
let invalidJson = "Not a valid JSON"
do {
let jsonData = try JSONSerialization.data(withJSONObject: self, options: .prettyPrinted)
return String(bytes: jsonData, encoding: String.Encoding.utf8) ?? invalidJson
} catch {
return invalidJson
}
}
func printJson() {
print(json)
}
}
suppose you have yourDicObj decoded from JSON and you want to see it as JSON before decoded on the console
usage in console :
lldb po yourDicObj.printJson
it will print as JSON
As a Swift newcomer, I am very confused about how to parse some JSON data obtained from an API. I am able to get the JSON data from the api using an alamofire request. At this point, I think I have an NSDictionary object, JSON as print(JSON) logs to console a good deal of JSON.
if let result = response.result.value {
let JSON = result as! NSDictionary
print("this is what JSON is")
print(JSON)
My question is, first, is JSON in fact an NSDictionary. Second, how would I access a value in the JSON. Do I need to first convert this to a data object. Or how do I get at the nested data.
For example, let's say the JSON looks like this:
{
"contact": {
"first": "Bob",
"second":"Jones"
}
}
I came across this code on SO:
let data = JSON(data: JSON)
print("data\(data["contact"]["first"])")
But it throws an error. I have swiftyJSON installed but happy for solution with or without it.
Thanks in advance for any suggestions
Can you try
if let result = response.result.value as? [String:Any] {
if let contact = result["contact"] as? [String:Any] {
if let first = contact["first"] as? String {
print(first)
}
}
}
also this
let data = JSON(data: JSON)
gives error because parameter should be of type Data not Dictionary
I would prefer to return Data from Alamofire request and use Decodable to parse it and convert to required model
TRY THIS!
if let data = response.data {
let jsonData = JSON(data: data)
print("data : \(jsonData["contact"]["first"].string)")
}
Swift4 introduce amazing Codable protocol.
Using Codable, we can model JSONObject or PropertyList file into equivalent Struct or Classes by writing very few lines of code.
There are many online tool available which creates model class from you JSON
(http://www.json4swift.com/)
Example
let decoder = JSONDecoder()
let parsedObject = try decoder.decode(Class.self, from: data)
You can find detail at below link:
https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types
Hey guys so I create a NSMutableArray send it to my mysql server convert it to base64, then when the app reads the data, it decodes the base64 code into a string format. Now im trying to convert the string back into an NSMutableArray. I cant seem to get it work heres the code that converts it to a string.
let string = String(data: (Data(base64Encoded:((data?.value(forKey: "14112017") as! NSArray)[0] as! NSDictionary)["data"] as! String)!), encoding: .utf8)!
So the answer to my question ended up converting my array to a JSONstring first which I did by using:
let jsonData: Data? = try? JSONSerialization.data(withJSONObject: UniversalArray)
let jsonString = String(data: jsonData!, encoding: .utf8)
then when retreiving it I get back my jsonString, however it has "\" which I replace using:
let cleanJsonString = myData.replacingOccurrences(of: "\\", with: "")
then to finally finish it off I just send this cleanJsonString to this function:
func convertToDictionary(text: String) -> Any? {
if let data = text.data(using: .utf8) {
do {
return try JSONSerialization.jsonObject(with: data, options: [])
} catch {
print(error.localizedDescription)
}
}
return nil
}
when calling this function I used this:
let array = convertToDictionary(text: myMutableArray) as? [AnyObject]
Thanks everyone for the amazing support, heres the answer to this bogus mess I created.
There are 2 parts to this: Serializing your array for transmission to your server, and then deserializing it from the server.
We need to see the code you use to serialize your array first. (The code that converts it to a string.) Based on what you post, it appears to be in JSON format. If so you may be able to skip the base64 encoding step, depending on what you're doing with the data. JSON is a good format for transmission to remote servers. You don't typically base64 encode JSON before transmission.
If you are receiving JSON that was then base64 encoded, you'll need to un-encode it back to data, and then use the JSONSerializer class to convert the JSON back to objects like arrays or dictionaries:
let data = Data(base64Encoded: base64DataFromServer)
guard let object = try? JSONSerialization.jsonObject(with: data) else {
return nil
}
(Note that the JSON you posted contains a dictionary as the top-level object, not an array.)
I'm calling an api in swift 3. And from the api I'm getting response in JSON String format. How to convert that JSON String to Dictionary or Array in Swift. Also that JSON string contains further array's and dictionaries.
I've tried using EVReflection tool. It's only converting the upper JSON object in dictionary. The nested dictionaries and array's are still in String format.
Try something like this, response is [String: Any] so you must cast to a any type
DispatchQueue.main.async {
do {
if let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String: Any] {
let j = json as NSDictionary
guard let resp = response as? HTTPURLResponse
else {
// No response from server
return
}
if resp.statusCode == 200 {
// You can put here some callback, this is a data you need
} else {
// Here is some error
}
}
} catch {
// And this is a error from server
}
}
You should receive jsonData which you can directly try JSONSerialization.
If for any reason you receive it as json String then you have to convert that string to jsonData first
// Here you have to convert Json String to jsonData
// if it's not Json String then skip this line
let jsonData = jsonString.data(using: .utf8)
// Try to convert it to json object
do {
let json = try JSONSerialization.jsonObject(with: jsonData, options: []) as! [String : Any]
// now you can try to parse your json
} catch let error as NSError {
print(error.localizedDescription)
}
Or as #Jay mentioned use Swiftyjson
I'm trying to integrate a login API in my iOS project. When i hit that API in browser it gives me correct JSON response. Whereas, when i call it in my app, i'm unable to read JSON. Code is as:
let url = NSURL(string: "myURL")
let request = NSURLRequest(URL: url!)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request) { (data, response, error) -> Void in
if error != nil {
print (error)
}
do {
//jsonDict is always nil
if let jsonDict = try self.jsonFromData(data!) {
print (jsonDict)
}
}
catch {
print ("hi")
}
}
jsonFromData is as:
private func jsonFromData(jsonData: NSData) throws -> [NSDictionary]?
{
var jsonDict: [NSDictionary]? = nil
do
{
jsonDict = try NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.AllowFragments) as? [NSDictionary]
}
catch
{
throw(error)
}
return jsonDict
}
Response of API, when hit in browser is as:
Please help me, what i am doing wrong. Thanks.
UPDATE:
I just checked that if i convert data to String, it gives correct value. i.e.
let string = NSString(data: jsonData, encoding: NSASCIIStringEncoding)
print (string)
//OUTPUT: Optional({"Authenticated":true,"CustomerID":000,"CustomerName":"TEMP","Members":[{"MemberID":000,"MemberNumber":"000","MembershipID":00,"MembershipExpiration":"\/Date(1517464799000-0600)\/","ValidBuyerTypes":[0]}]})
Look at your code where you decode the JSON and the as? statement. You are trying to get an array of NSDictionary. Your JSON as printed contains a single dictionary, not an array.
This looks right to me. The only thing I can think is that (despite what the string output looks like) the top level container of your response is NOT an NSDictionary. In your jsonFromData function, instead of assuming the result of JSONObjecWithData will be an NSDictionary, I would say:
let iDunnoWhatThisIs = try NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.AllowFragments) // don't cast this to NSDictionary
and see what you get back. It should either be a dictionary or an array, however, since you have NSJSONReadingOptions.AllowFragments set for the options, it's possible that it could be something else entirely. Start with making SURE you're actually getting back what you're assuming you are and go from there.
Try using NSKeyedUnarchiver instead:
jsonDict = NSKeyedUnarchiver.unarchiveObjectWithData(jsonData)! as NSDictionary