Trouble parsing JSON with Swift using SwiftyJSON - json

I am new to swift and I am trying to parse some simple JSON data I am retrieving from a private API that I have. I am using the SwiftJSON library.
No matter what I do I cannot assign the variable "videoUploadId" with the value of "video_upload_id" coming from the JSON response. I hope i provided enough info to get some help. Thanks
Here is a segment of the code
let task = session.dataTaskWithRequest(request, completionHandler: { (data : NSData!, response, error : NSError!) -> Void in
if (error == nil) {
// Success
let statusCode = (response as NSHTTPURLResponse).statusCode
println("Status Code: \(statusCode)\r\n")
println("Response: \(response)\r\n")
println("Data: \(data)\r\n")
let dataContent = NSString(data: data!, encoding: NSUTF8StringEncoding)!
println("UTF8 Data: \(dataContent)\r\n")
let json = JSON(dataContent)
if let videoUploadId = json["video_upload_id"].int {
println("Video Upload ID (Dict: int): \(videoUploadId)")
}
else if let videoUploadId = json["video_upload_id"].string {
println("Video Upload ID (Dict: string): \(videoUploadId)")
}
else if let videoUploadId = json[0].int {
println("Video Upload ID (Array: int): \(videoUploadId)")
}
else if let videoUploadId = json[0].string {
println("Video Upload ID (Array: string): \(videoUploadId)")
}
else {
println(json["video_upload_id"].error)
}
}
else {
// Failure
println("URL Session Task Failed: %#", error.localizedDescription);
}
})
task.resume()
This is what I am receiving from my console:
Login Response: HTTP 200
Status Code: 201
Response: { URL: https:////videos/uploads/ } { status code: 201, headers {
Connection = "Keep-alive";
"Content-Length" = 24;
"Content-Type" = "application/json";
Date = "Sun, 25 Jan 2015 01:02:42 GMT";
Location = "https:////videos/uploads/";
Server = "Apache/2.2.15 (CentOS)";
"Set-Cookie" = "session=eyJzZXNzaW9uX3Rva2VuIjp7IiBiIjoiUzAxWGFYRnlVVGM1YjBsa1kxWkJiV2xrYVZwcFZXdDFiR0ZLYW5GQ1VqRjFjbk5GIn19.B6XSMg.HXatQ76ZFaoZEQsnNu1BgsVECKA; HttpOnly; Path=/";
} }
Data: <7b227669 64656f5f 75706c6f 61645f69 64223a20 3736307d>
UTF8 Data: {"video_upload_id": 760}
Optional(Error Domain=SwiftyJSONErrorDomain Code=901 "Dictionary["video_upload_id"] failure, It is not an dictionary" UserInfo=0x170238620 {NSLocalizedDescription=Dictionary["video_upload_id"] failure, It is not an dictionary})
As you can see from the code and console output, I am attempting to set the variable in several different ways all of which seem to fail. I am receiving the error "Dictionary["video_upload_id"] failure, It is not an dictionary" I even tried prepending "[" and appending "]" to try to see if its a formatting issue.
Any clues?

You are doing the initialization wrong. You should use:
let json = JSON(data:data) // data is NSData!
Converting NSData to NSString is not necessary, and somehow wrong for this. SwiftyJSON can only be initialized with NSData or Swift object.

Related

swift json serialization error : Unable to convert data to string

I'm a Korean developer, and I'm not familiar with swift.
Unfortunately the server I need to connect with is encoded in euc-kr format.
If the JSON contains Korean, it outputs the following error: Unable to convert data to string
I have verified through Json Parser that the shape of my JSON is not strange.
I am using Alamofire library for server connection.
This is my Json structure.
{"result":[{"id":"2659","member_id":"sexyback","nickname":"BJ%ED%8F%AC%EB%A1%9C%EB%A6%AC","live_YN":"N","19":"all","intro":"엄청나게 재미있는 포로리","fan":"open","acc_good":"","acc_fav":"","img_url":"%2Fpx%2Ffiles%2Fdotv_2659_f1_657.jpg"}],"total":[{"total":"6"}],"status":[{"status":"success"}]}
My logic is:
static func requestHotBJList() async -> Any {
let url = WebConstant.getHotBJList()
DLogUtil.debug(tag: #file, content: url)
do {
let data = try await HttpWrapper.requestGetTest(withUrl: url)
return JSONUtil.createJSONObject(data: data)
} catch {
return error
}
}
Get data from server via Http Wrapper.request Get. Try JSON Parsing through JSONUtil.createJSONObject(data: data) with the data of the Data type imported from here.
I get data from the server in the following way:
public static func requestGet(
withUrl url: String,
withHeader header: HTTPHeaders? = nil
) async throws -> Data {
try await withUnsafeThrowingContinuation { continuation in
AF.request(url, method: .get, headers: header).validate().responseData { response in
if let data = response.data {
continuation.resume(returning: data)
return
}
if let error = response.error {
continuation.resume(throwing: error)
return
}
fatalError("fatal error")
}
}
}
The data parsing logic is as follows :
public static func createJSONObject(data: Data) -> [String : Any] {
do {
DLogUtil.debug(tag: #file, content: "data ? \(data)")
let json = try JSONSerialization.jsonObject(with: data, options: []) as! [String : Any]
return json
}
catch let error as NSError {
DLogUtil.debug(tag: #file, content: error)
return [String : Any]()
}
}
Error is output during the parsing process. I've searched a lot, but I can't find it.
With help from #workingdogsupportUkraine, I found a way. After converting data type to NSString, NSString is encoded in utf-8 format.
var dataString = NSString(data: data, encoding: CFStringConvertEncodingToNSStringEncoding(0x0422))
var datadata = dataString!.data(using: String.Encoding.utf8.rawValue)
let json = try JSONSerialization.jsonObject(with: datadata!, options: []) as! [String : Any]
return json

Converting a String to json in Swift. for sending in a websocket

I have a JS to send Json via websocket. as follows:
function senddata()
{
var obj = {};
var arrayOfRequests = [];
arrayOfRequests.push({
"id":22,
"repeat":false,
})
obj.DataReq = arrayOfRequests;
var stringToSend = JSON.stringify(obj);
websocketConnection.send( stringToSend );
}
This code works as expected, and the server sends back the requested info.
I am trying to do the same thing in swift.
func send(text: String) {
let message = text
guard let json = try? JSONEncoder().encode(message),
let jsonString = String(data: json, encoding: .utf8)
else {
return
}
webSocketTask?.send(.string(jsonString)){ error in
if let error = error {
print("Error sending message", error)
}
}
}
send(text: "{“DataReq”:[{“id”:22,“repeat”:false}]}")
With this the server does not send any response.
If Connect both of these examples to a websocket echo server
the JS code sends {"DataReq":[{"id":22,"repeat":false}]}
while the Swift codes send "{"DataReq":[{"id":9,"repeat":false}]}".
any help is appreciated.
Encoding a JSON string to JSON is pointless. Remove the encoding part
func send(text: String) {
webSocketTask?.send(.string(text)){ error in
if let error = error {
print("Error sending message", error)
}
}
}
And in the send line the double quotes are invalid. Use this syntax
send(text: #"{"DataReq":[{"id":22,"repeat":false}]}"#)

Issue with JSON decoding in Swift (data missing)

I'm trying to query the NASA image API (latest docs here) using Swift 4. I set up and tested my request with JSONPlaceholder to make sure my network request and decoding was setup correctly. Everything was working fine, but when I switched the URL and corresponding JSON data structure, I get an error saying 'the data couldn't be read because it is missing.'
I've used Postman to verify that JSON is being returned, and to build the JSON data structure.
Is this a common error from decoding JSON or is it something with the network request? Or am I missing something with using the NASA API?
let NASAURL = URL(string: "https://images-api.nasa.gov/search?q=moon")
let session = URLSession(configuration: .default)
let task = session.dataTask(with: NASAURL!) { (rdata, response, error) in
NSLog("Data Description: " + (rdata!.debugDescription) + "\nResponse: " + response.debugDescription + "\nError Description: " + error.debugDescription)
guard rdata != nil else{
NSLog("No data")
return
}
guard error == nil else{
NSLog(response.debugDescription + "\n")
NSLog(error.debugDescription)
NSLog(error.debugDescription)
return
}
let decoder = JSONDecoder()
do{
NSLog(rdata.debugDescription)
let usr = try decoder.decode(Collect.self, from: rdata!) // Throws
NSLog(usr.href)
} catch {
NSLog("Error: " + error.localizedDescription)
}
}
task.resume()
// Collect is in its own class/file
struct Collect: Codable {
var href: String
//var items: [Items]
}
Below is the printout from the above log statements...
2017-09-29 19:50:24.135288-0500 OpenNASA[16993:10774203] Data Description: 67669 bytes
Response: Optional(<NSHTTPURLResponse: 0x60000003db00> { URL: https://images-api.nasa.gov/search?q=moon } { status code: 200, headers {
"Access-Control-Allow-Origin" = "*";
"Cache-Control" = "public, max-age=300, s-maxage=600";
"Content-Encoding" = gzip;
"Content-Length" = 9334;
"Content-Type" = "application/json; charset=UTF-8";
Date = "Sat, 30 Sep 2017 00:48:11 GMT";
Server = "nginx/1.4.6 (Ubuntu)";
"Strict-Transport-Security" = "max-age=31536000";
Vary = "Accept-Encoding";
"access-control-allow-headers" = "Origin,Content-Type,Accept,Authorization,X-Requested-With";
"access-control-allow-methods" = GET;
} })
Error Description: nil
2017-09-29 19:50:24.137324-0500 OpenNASA[16993:10774203] Optional(67669 bytes)
2017-09-29 19:56:01.843750-0500 OpenNASA[16993:10774203] Error: The data couldn’t be read because it is missing.
You Codable should be like below:
struct Collect: Codable {
var collection: Links
}
struct Links: Codable {
var links: [Href]
}
struct Href: Codable {
var href: String
}
You have to call like below:
let usr = try decoder.decode(Collect.self, from: rdata!) // Throws
let links = usr.collection.links
for link in links {
print(link.href)
}

unknown type while trying to parse JSON data With SwiftyJSON under iOS 7

I am using Alamofire for networking and SwiftyJSON for parsing server response in my iOS app.
I always get unknown while trying to do this println(JSON(data!))
Here is my request code :
Alamofire.request(.GET, URLString: "http://httpbin.org/get", parameters: ["foo": "bar"])
.response { (request, response, data, error) in
println("request ==== \(request)")
println("response ==== \(response)")
println("error ==== \(error)")
println("json ==== \(JSON(data!))")
println("data ==== \(data)")
}
And here is my console output :
request ==== <NSMutableURLRequest: 0x15e9a4e0> { URL: http://httpbin.org/get?foo=bar }
response ==== Optional(<NSHTTPURLResponse: 0x15ddc910> { URL: http://httpbin.org/get?foo=bar } { status code: 200, headers {
"Access-Control-Allow-Credentials" = true;
"Access-Control-Allow-Origin" = "*";
Connection = "keep-alive";
"Content-Length" = 430;
"Content-Type" = "application/json";
Date = "Wed, 04 Feb 2015 09:12:45 GMT";
Server = nginx;
} })
error ==== nil
json ==== unknown
data ==== Optional(<7b0a2020 22617267 73223a20 7b0a2020 20202266 6f6f223a 20226261 72220a20 207d2c20 0a202022 68656164 65727322 3a207b0a 20202020 22416363 65707422 3a20222a 2f2a222c 200a2020 20202241 63636570 742d456e 636f6469 6e67223a 2022677a 69703b71 3d312e30 2c636f6d 70726573 733b713d 302e3522 2c200a20 20202022 41636365 70742d4c 616e6775 61676522 3a202266 723b713d 312e302c 656e3b71 3d302e39 2c64653b 713d302e 382c7a68 2d48616e 733b713d 302e372c 7a682d48 616e743b 713d302e 362c6a61 3b713d30 2e35222c 200a2020 20202248 6f737422 3a202268 74747062 696e2e6f 7267222c 200a2020 20202255 7365722d 4167656e 74223a20 224f7545 73744d6f 6e43616d 696f6e2f 636f6d2e 50697865 6c734163 6164656d 792e4f75 4573744d 6f6e4361 6d696f6e 2028313b 204f5320 56657273 696f6e20 372e312e 32202842 75696c64 20313144 32353729 29220a20 207d2c20 0a202022 6f726967 696e223a 20223139 372e3134 2e31302e 3234222c 200a2020 2275726c 223a2022 68747470 3a2f2f68 74747062 696e2e6f 72672f67 65743f66 6f6f3d62 6172220a 7d0a>)
Am i doing something wrong?
The unknown value being printed is coming from SwiftyJSON. It appears that you are using the incorrect initializer. Instead you want to try the following.
var parsingError: NSError?
let json = JSON(data: dataFromServer, error: &error)
println(json)
println(parsingError)
This will run NSJSONSerialization.JSONObjectWithData over your NSData that you send into SwiftyJSON. If it succeeds, you'll get a valid JSON object. If it fails, you will still get your unknown type but the parsingError will tell you why parsing failed.
One last tip is that you could try to encode the dataFromServer to be able to visualize it properly. Here's how you could do that.
if let dataFromServer = dataFromServer as? NSData {
if let encodedData = NSString(data: dataFromServer, encoding: NSUTF8StringEncoding) {
println(encodedData)
}
}
Hope that helps!
I think that the problem was relative to the Alamofire library under iOS7. I ended up by working with AFNetworking and parsing web service response with SwiftyJSON without any strange problems.

How to call rest web service from swift

I am trying to follow a tutorial - which failed and having found some code on stack over flow Make REST API call in Swift decided to try this approach instead. The following code is a copy and paste (I know!) with a change of URL yet I seem to be getting an error printed to the console rather than the JSON - the error being largely unhelpful - 0x0000000000000000
The JSON appears to print to the browser window so I am not fully sure what might be wrong with this approach? Please could someone provide some help as to why this might not be working?
Thanks
var url : String = "http://www.flickr.com/services/rest/?method=flickr.test.echo&format=json&api_key=d6e995dee02d313a28ed4b799a09b869"
var request : NSMutableURLRequest = NSMutableURLRequest()
request.URL = NSURL(string: url)
request.HTTPMethod = "GET"
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue(), completionHandler:{ (response:NSURLResponse!, data: NSData!, error: NSError!) -> Void in
var error: AutoreleasingUnsafeMutablePointer<NSError?> = nil
let jsonResult: NSDictionary! = NSJSONSerialization.JSONObjectWithData(data, options:NSJSONReadingOptions.MutableContainers, error: error) as? NSDictionary
if (jsonResult != nil) {
println(jsonResult);
} else {
// couldn't load JSON, look at error
println(error);
}
})
The problem is that the call returns data in JSONP not JSON
Your code would work ok if tested with a correct JSON like http://ip.jsontest.com
To make it work with Flickr you have to modify it as follows:
var json_str:NSString = NSString(data: data, encoding: NSUTF8StringEncoding)
json_str = json_str.substringFromIndex(14)
json_str = json_str.substringToIndex(json_str.length-1)
let new_data:NSData = json_str.dataUsingEncoding(NSUTF8StringEncoding)!
var error: AutoreleasingUnsafeMutablePointer<NSError?> = nil
let jsonResult: NSDictionary! = NSJSONSerialization.JSONObjectWithData(new_data, options:NSJSONReadingOptions.MutableContainers, error: error) as? NSDictionary
if (jsonResult != nil) {
println(jsonResult);
} else {
// couldn't load JSON, look at error
println(error);
}