Swift Console Output to Text Label - json

I am trying to take console output from a json request and post it as a text label for the user. I can't seem to get it to work. Any advice? Thanks! It prints fine in the console, but won't work for the "self.resultLabel.text = json"
do {
let json = try NSJSONSerialization.JSONObjectWithData(data!, options:.AllowFragments)
print(json)
dispatch_async(dispatch_get_main_queue(),{
self.myActivityIndicator.stopAnimating()
self.myImageView.image = nil;
self.resultLabel.text = json
func loadSites(){
//trying to get the post to show up in the place of the invisible label
}
});
}catch {
print(error)
}

I am not sure why exactly you want to show raw json to users in UILabel but you should convert json to a string if you want to assign it to UILabel's text property.
There is a description method, which is always used in Objective-C whenever you print an NSObject subclass via NSLog.
This method is also available in Swift:
self.resultLabel.text = (json as AnyObject).description

Related

error processing json data: The data couldn’t be read because it isn’t in the correct format

This error has been annoying all morning, I'm trying to retrieve JSON in the format:
song = {
'artist':'Tom Waits',
'song':'New Coat Of Paint',
'lyrics':'Let\'s put a new coat of paint on this lonesome old town\nSet \'em up, we\'ll be knockin\' em [...]',
'url':'http://lyrics.wikia.com/Tom_Waits:New_Coat_Of_Paint'
}
from this URL: JSON URL
This is the function I'm using to parse the data:
func parseJSONFromData(_ jsonData: Data?) -> [String : AnyObject]?
{
if let data = jsonData {
do {
let jsonDictionary = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as? [String : AnyObject]//Parses data into a dictionary
return jsonDictionary
} catch let error as NSError {
print("error processing json data: \(error.localizedDescription)")
}
}
return nil
}
}
If you go to the site http://json.parser.online.fr it will let you paste in data and check to see if it's valid JSON or not. Yours is not.
As others have said, strings need to be enclosed in double quotes, not single quotes, and the "=" is not valid.
It would be quite easy to write code that would replace all occurrences of ' with ". The song = bit is less clear. The correct format for JSON would be:
{
"song": {
"artist":"Tom Waits",
"song":"New Coat Of Paint",
"lyrics":"Let\"s put a new coat of paint on this lonesome old town\nSet \"em up, we\"ll be knockin\" em [...]",
"url":"http://lyrics.wikia.com/Tom_Waits:New_Coat_Of_Paint"
}
}
Or you could get rid of the outer dictionary entirely:
{
"artist":"Tom Waits",
"song":"New Coat Of Paint",
"lyrics":"Let\"s put a new coat of paint on this lonesome old town\nSet \"em up, we\"ll be knockin\" em [...]",
"url":"http://lyrics.wikia.com/Tom_Waits:New_Coat_Of_Paint"
}
You need to look at your data and figure out what's wrong with it in the general case that makes it not legal JSON.
EDIT:
After further digging, it seems that the URLs you're using are returning JavaScript, not JSON. Try an URL like this instead:
http://lyrics.wikia.com/wikia.php?controller=LyricsApi&method=getSong&artist=Tom%20Waits&song=new%20coat%20of%20paint
That should give you the lyrics of the Tom Waits song New Coat of Paint in well-formed JSON.
This Github page gives info on the search parameters you can use to query that site and get lyrics:
https://github.com/Wikia/app/blob/dev/extensions/wikia/LyricsApi/LyricsApiController.class.php#L10-L15

How to debug network request Swift

I'm making a http request to an API with JSON in the body of the request. I know for a fact that my Dictionary<String, String> containing the JSON data is correct, still I'm getting a response from the server that my input data is not valid. I'm doing something very similar to this: Swift 2.0 url post request. I even tried the extension suggested there but without success.
how should I debug this? I can't find any way to print my whole request to the console. I want to know what my URLRequest actually contains just before I send the request. Also, I want to know that this hex gibberish is actually the right gibberish I meant it to be, how should I do this?
Nothing special about that? Just write an extension and print whatever you want
example:
extension Data {
func toString() -> String? {
return String(data: self, encoding: .utf8)
}
}
extension URLRequest {
func log() {
print("\(httpMethod ?? "") \(self)")
print("BODY \n \(httpBody?.toString())")
print("HEADERS \n \(allHTTPHeaderFields)")
}
}
Usage:
request.log()
Sample log:
POST https://httpbin.org/
BODY
Optional("password=xxx&username=xxx")
HEADERS
Optional(["Content-Type": "application/x-www-form-urlencoded; charset=utf-8"])

Swift 2.0 How to parse JSON?

I am coding a hangman game and am loading the possible words into my app using json text files. I tried to follow the examples of others on this website but I am getting errors from Xcode.
I tried the following code based on another answer:
import Foundation
var error: NSError?
let jsonData: NSData = /* get your json data */
let jsonDict = NSJSONSerialization.JSONObjectWithData(jsonData, options: nil, error: &error) as NSDictionary
But I got an errors on line 4 with jsonDict that said "call can throw but is not marked with try, and the error is not handled" and "Type JSONReadingOptions does not conform to protocol NilLiteralConvertible".
Here is the JSON File I would like to parse:
{
“wordList” : {
“difficulty” : “Easy”
“list” : [
“fireplace”,
“apple”,
“january”,
“tooth”,
“cookies”,
“mysterious”,
“essential”,
“magenta",
“darling”,
“pterodactyl”
]}}
I would like to be able to go into my list array and get values. Thank you very much for any help!
In Swift 2 you need to use the new error handling API instead of passing a reference to an NSError:
do {
let jsonDict = try NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions(rawValue: 0)) as? NSDictionary
if let jsonDict = jsonDict {
// work with dictionary here
} else {
// more error handling
}
} catch let error as NSError {
// error handling
}
You also can't pass nil as value to the options parameter, you need to pass a value of type NSJSONReadingOptions.
That said, the most common approach for parsing JSON in Swift is currently using third party libraries, such as Argo because they can save you a lot of code that is necessary to validate and safely cast the content of your JSON data to the correct Swift types.

How to parse JSON in Swift 2?

I have a PHP web api that returns json in the following format:
{"users":[
{"user": {id:"1","name":"ahmad"}},
...
]}
In my Swift 2 code, I am able to retrieve the data above store it in an NSArray named users
Now, I need to iterate throw each user to convert it into an object:
for user in users {
print("found: \(user)")
}
That ouputs something like:
found: {
user = {
id = 1;
name = ahmad;
};
}
but when I try to access any element of that object I get an error:
let id = user["user"]["id"] //does not work: Xcode wont compile
let id2 = user["user"]!["id"]! //does not work: Xcode wont compile
let id3 = user!["user"]!["id"]! //does not work: Xcode wont compile
Then I tried :
if let u=user["user"] { //does not work: Xcode wont compile
// do somthing
}
I put a break point at print("\(user)") to see what is going on, and here is what I found:
When I print the description of each individual user I get:
How can I access the elements of this JSON data in Swift 2?
A NSArray only holds AnyObject so you have to cast it (to Array<Dictionary<String, Dictionary<String, String>>>. Below you see the shorthand):
// this is a forced cast and you probably get runtime errors if users cannot be casted
for user in users as! [[String : [String : String]]] {
print("found: \(user)")
}

Safe Dynamic JSON Casts In Swift

I suspect that I am not quite grokking Swift 1.2, and I need to RTFM a bit more.
I'm working on a Swift app that reads JSON data from a URI.
If the JSON data is bad, or nonexistent, no issue. The JSON object never instantiates.
However, if the JSON data is good JSON, but not what I want, the object instantiates, but contains a structure that is not what I'm looking for, I get a runtime error.
I looked at using Swift's "RTTI" (dynamicType), but that always returns "<Swift.AnyObject>", no matter what the data is.
I want the JSON to be a specific format: An array of Dictionaries:
[[String:String]]! JSON: [{"key":"value"},{"key","value"},{"Key":"value"}]
If I feed it a single element:
{"Key":"value"}
The routine I have tries to cast it, and that fails.
I want to test the JSON object to make sure that it has a structure I want before casting.
if(nil != inData) {
let rawJSONObject: AnyObject? = NSJSONSerialization.JSONObjectWithData(inData, options: nil, error: nil)
println("Type:\(rawJSONObject.dynamicType)")
if(nil != rawJSONObject) {
// THE LINE BELOW BLOWS UP IF I FEED IT "BAD/GOOD" JSON:
let jsonObject: [[String:String]]! = rawJSONObject as! [[String:String]]!
// I NEED TO TEST IT BEFORE DOING THE CAST
if((nil != jsonObject) && (0 < jsonObject.count)) {
let jsonDictionary: [String:String] = jsonObject[0]
if("1" == jsonDictionary["semanticAdmin"]) { // We have to have the semantic admin flag set.
let testString: String! = jsonDictionary["versionInt"]
if(nil != testString) {
let version = testString.toInt()
if(version >= self.s_minServerVersion) { // Has to be a valid version for us to pay attention.
self.serverVersionAsInt = version!
}
}
}
}
}
}
My question is, is there a good way to test an NSJSONSerialization response for the structure of the JSON before uwinding/casting it?
I feel as if this question may be closer to what I need, but I am having trouble "casting" it to my current issue.
You can use safe unwrapping to test the type of your raw object, for example:
if let jsonObject = rawJSONObject as? [[String:String]] {
// jsonObject is an array of dictionaries
} else if let jsonObject = rawJSONObject as? [String:String] {
// jsonObject is a dictionary
// you can conform it as you wish, for example put it in an array
} else {
// fail, rawJSONObject is of another type
}
Currently, your code crashes because of the forced unwrapping, with !, of values that will be nil if the cast fails.