Swift 3 Dictionary JSON - json

in school we're creating a program to track Sailing Races.
I'm currently developing the GPS Tracker App for the sailing teams.
The JSON to send to our Api must look like this:
{"hash":"asdh832","positions":[{"longitude":13.340532999999999,"latitude":52.4965431,"time":1488182463461},{"longitude":13.3175489,"latitude":52.4927039,"time":1488195535705},{"longitude":13.3175489,"latitude":52.4927039,"time":1488195536657}]}
First the Hash for the Team and positions in a Array(if the smartphone doesn't have a internet connection atm to send them later)
I have a "positions" Array Dictionary:
var positions = Array<Dictionary<String,String>>()
positions.append( ["longitude":String(location.coordinate.longitude),
"latitude":String(location.coordinate.latitude),
"time":String(Int64(location.timestamp.timeIntervalSince1970 * 1000.0))])
// Times 2 to test
positions.append( ["longitude":String(location.coordinate.longitude),
"latitude":String(location.coordinate.latitude),
"time":String(Int64(location.timestamp.timeIntervalSince1970 * 1000.0))])
let data2 = try JSONSerialization.data(withJSONObject: positions, options: [])
let dataString2 = String(data: data2,encoding: String.Encoding.utf8)!
print(dataString2)
The Result of print(dataString2) is:
[{"latitude":"52.4965211222075","longitude":"13.3405919673345","time":"1488194768467"},{"latitude":"52.4965211222075","longitude":"13.3405919673345","time":"1488194768467"}]
which is correct. Now I want to combine it with a the Hash:
let params: Dictionary<String, String> = ["hash":"asdh832","positions": dataString2]
let data = try JSONSerialization.data(withJSONObject: params , options: [])
let dataString = String(data: data,encoding: String.Encoding.utf8)!
but the now the result after "positions:" looks kinda weird:
{"hash":"asdh832","positions":"[{\"latitude\":\"52.4966040328522\",\"longitude\":\"13.3402242104124\",\"time\":\"1488195406482\"},{\"latitude\":\"52.4966040328522\",\"longitude\":\"13.3402242104124\",\"time\":\"1488195406482\"}]"}
without these extra " and \ it would be correct but I just don't know how to build it like this.
I'm using Swift 3 with Xcode 8.2.1

Make JSON string at last means don't create JSON string from Array positions instead of that set that Array with your params dictionary with key positions instead of setting string.
var positions = Array<Dictionary<String,String>>()
positions.append(["longitude":String(location.coordinate.longitude),
"latitude":String(location.coordinate.latitude),
"time":String(Int64(location.timestamp.timeIntervalSince1970 * 1000.0))])
positions.append(["longitude":String(location.coordinate.longitude),
"latitude":String(location.coordinate.latitude),
"time":String(Int64(location.timestamp.timeIntervalSince1970 * 1000.0))])
//Now set this positions array with positions key in params dictionary
let params: Dictionary<String, Any> = ["hash":"asdh832","positions": positions]
let data = try JSONSerialization.data(withJSONObject: params , options: [])
let dataString = String(data: data,encoding: String.Encoding.utf8)!

The Result of print(dataString2) is: [...] which is correct.
No.
You're serialising latitude, longitude and timestamp as strings, while they should be numbers (notice the quotes).
[...] but the now the result after "positions:" looks kinda weird
That's because you double serialise dataString2.
Do not call JSONSerialization.data twice but create one big Dictionary<String, Any> that contains all structured data and then perform the serialisation in one call.

Related

How can I get the JSON response in dictionary format in swift3?

I'm working on JSON serialization like below code:
let jsonData: Data? = try? JSONSerialization.data(withJSONObject: abc, options: .prettyPrinted)
let parsedDict = String(data: jsonData!, encoding: String.Encoding.utf8)
print(" parse Dict Value \(parsedDict!)")
abc data is:
{
"ActedTime" = "2017-09-19 12:04:12",
"EventDate" = "2017-10-06 07:03:29"
}
After completion of serialization, the response value is:
"{\n \"ActedTime\" : \"2017-09-19 12:04:12\",\n \"EventDate\" : \"2017-10-06 07:03:29\”}”
I printed the parsedDict like below:
{
"ActedTime" : "2017-09-19 12:04:12",
"EventDate" : "2017-10-06 07:03:29"
}
The stored data seems like string format, but data is printed like dictionary.
How can I get dictionary format for sent the parameters to another API like dictionary format.
Please help me,
Thanks in Advance.
Omit .prettyPrinted, the server doesn't care anyway.
let jsonData = try? JSONSerialization.data(withJSONObject: abc)
And if the object is supposed to be a dictionary, why do you serialize it at all?
However if the data is supposed to be passed in a POST request as httpBody pass jsonData rather than parsedDict.

change JSON to String in Swift [duplicate]

This question already has answers here:
Simple and clean way to convert JSON string to Object in Swift
(17 answers)
Closed 5 years ago.
I got JSON file from API but the content looks like this:
[
"https:\/\/seekingalpha.com\/article\/4125943-apple-homepod-delay-big-deal?source=feed_symbol_AAPL"
]
Suppose the JSON Object above is named as json. Then I just convert the object to string using String() method.
strings = String(json)
When I changed it to String type, it seems to get unnecessary '\n' and whitespace in it.
"[\n \"https:\\/\\/seekingalpha.com\\/article\\/4125943-apple-homepod-delay-big-deal?source=feed_symbol_AAPL\"\n]"
So it seems like the content of the JSON file is:
["\n""whitespace""whitespace""String""\n"]
When I changed it to String type, Swift just treats all the elements in it as a whole and wrapped it as a string.
My question is, how to extract the String inside so it looks like:
"https:\\/\\/seekingalpha.com\\/article\\/4125943-apple-homepod-delay-big-deal?source=feed_symbol_AAPL\"
As I am not so familiar with Swift so how to extract String or JSON Object is not easy for me. Any hints or help will be appreciated.
Swift 3,4 :
The given JSON format is Array of String.
if let json = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String]{
let firstElement = json?.first ?? "Element Not Found!"
print(firstElement)
}
Swift 4:
if let json = try? JSONDecoder().decode(Array<String>.self, from: data){
let firstElement = json.first ?? "First Element Not Found!"
print(firstElement)
}
Note:
If your the Array contains more than one String. Here,urls is the class variable. i.e.,var urls = [String]()
Swift 3,4 :
if let json = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String]{
if json != nil{
self.urls = json!
}
print(self.urls)
}
Swift 4:
if let json = try? JSONDecoder().decode(Array<String>.self, from: data){
self.urls = json
}
1. You will first have to convert JSON to Data
2. Convert data to string wrt to encoding
func jsonToString(jsonTOConvert: AnyObject){
do {
let data = try JSONSerialization.data(withJSONObject: jsonTOConvert, options: JSONSerialization.WritingOptions.prettyPrinted)
let convertedString = String(data: data, encoding: String.Encoding.utf8)
} catch let myJSONError {
print(myJSONError)
}
}
You are asking that a String be created with the contents:
[
"https:\/\/seekingalpha.com\/article\/4125943-apple-homepod-delay-big-deal?source=feed_symbol_AAPL"
]
The string object is doing exactly what you told it to — the thing you've asked it to represent begins with a square bracket, then there's a line break, then two spaces, etc, so the string contains a square bracket, then a line break, then two spaces, etc. There is no 'unnecessary' \n, there is only the \n you told it to put in.
If you obtained a JSON object then you need to parse it as JSON. JSONSerialization will do that job. What you've actually got is an array with a single item, which is a string. So JSONSerialization will return an array. The first item of that should be a string that is the seekingalpha.com URL.

having trouble drilling down into response json using alamofire. Swift

Ok so im having trouble drilling down into the response json that is retrieved in the below code.
Snapshot 1:
Snapshot 2:
I get the json above as a response, yet when I try to drill down into the json I cannot access the key "Address" or any other key that is held under bookings. it finds bookings but then assigns the variables i created for each key's value (address, state, zipcode, and city) and assigns these variables as null. My only theory is that the response json has "()" right after bookings instead of the normal "{}". Those brakets do appear after the parentheses, so how would i drill into that with out a key? I am still new to the app dev world so i could be completely wrong, just this request method has worked for me in the past when i've received "{}" after the first key.
1) You are using method valueForKeyPath() to get value from dictionary.
Change it to valueForKey().
2) Value for key "bookings" will give you array.
Try this code.
let data = JSON as! NSDictionary;
//value for key "bookings" will give you array
if let bookings = data.valueForKey("bookings") as? NSArray {
let bookingObj = bookings[0] as! NSDictionary;
self.address = bookingObj.valueForKey("address");
self.state = bookingObj.valueForKey("state");
self.zip = bookingObj.valueForKey("zip");
self.city = bookingObj.valueForKey("city");
}
FYI Please Note that, method valueForKeyPath() returns array of value for particular key from the array of dictionaries.
e.g. suppose you have multiple objects of bookings array, and you use
let arrayAddresses = bookings.valueForKeyPath("address") as! NSArray
this will return string array containing only address of all object.
Another point, '()' means Array Value, '{}' means Dictionary value.
I'd suggest using Swift types (like [String: AnyObject]) instead of Foundation types (like NSDictionary), and on top of that, you should print out when something fails so you know what's wrong. So starting from your let data = ... line, try this instead:
if let data = JSON as? [String: AnyObject],
bookings = data["bookings"] as? [[String: AnyObject]],
booking = bookings[0] {
self.address = booking["address"] as? String
self.state = booking["state"] as? String
self.zipCode = booking["zip"] as? String
self.city = booking["city"] as? String
print(self.address)
} else {
print("Couldn't parse booking from JSON")
}
More on why typing is important (and why you should use [[String: AnyObject]] instead of NSArray) in this article. You can be more specific and more concise if you use proper types.

SwiftyJSON string-value empty

I have a problem with parsing JSON in Swift. I use the SwiftyJSON-framework.
My data comes from the network:
let dataString : NSString = NSString(data: data, encoding: NSUTF8StringEncoding)!;
printing this:
println("Received data: \(dataString)")
gives my JSON:
Received data: {"result":"success"}
But when I try to read the result-value:
let json = JSON(dataString);
println(json["result"].stringValue); //<-- empty string
then the output is empty. I've tried different approaches, like:
println(json[1]["result"].stringValue); //<-- empty string
println(json["result"]); //<-- prints "null"
but nothing worked so far. What am I doing wrong?
Edit:
This is server side (Java):
String response = client.isAuthenticated() ? "success" : "fail";
client.send(new JSONObject().put("result", response).toString());
To read the data I use CocoaAsyncSocket:
func socket(sock: GCDAsyncSocket!, didReadData data: NSData!, withTag tag: Int)
The error I get is:
Dictionary["result"] failure, It is not an dictionary
Edit2:
I found out that the problem is in the data:
let dataFromString = dataString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)?
has a length of 22 bytes. If I set
dataString : NSString = "{\"result\":\"success\"}"
and do the same again, its length is 20 bytes. My data has two bytes 0x0014 at beginning:
<7b227265 73756c74 223a2273 75636365 7373227d> //<-- correct
<00147b22 72657375 6c74223a 22737563 63657373 227d> // <-- mine
If I remove the two byes with
dataFromString!.subdataWithRange(NSMakeRange(2, 20))
the JSON can be parsed correctly.
Edit3 (my Solution):
The problem was the DataOutputStream I used in the Java-Service. It added two bytes to my JSON. I replaced it with BufferedOutputStream and now it works as expected.
You should get the NSData from the String, and initialize the JSON object with it, here's an example:
let dataString : NSString = "{\"result\":\"success\"}"
if let dataFromString = dataString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) {
let json = JSON(data: dataFromString)
print(json["result"])
}
Read More: SwiftyJSON - initialization
You should construct JSON with init(data:) constructor with NSData.
Try:
let json = JSON(data: data)

How to display indirectly given unicode character in Swift?

In a JSON data file, I have a unicode character like this:
{
”myUnicodeCharacter”: ”\\u{25a1}”
}
I know how to read data from JSON files. The problem occurs when it contains characters which are represented as above.
I read it in to a String variable, myUnicodeCharacterString, which gets the value ”\u{25a1}”. I couldn't by the way use a single slash in the JSON data file because in such case it doesn't recognize the data in the file to be a proper JSON object, returning nil.
However, the value is not encoded to its graphical representation when it’s assigned to something for displaying it, for example a SKLabelNode:
mySKLabelNode.Text = myUnicodeCharacterString // displays ”\u{25a1}” and not a hollow square
The problem boils down to this:
// A: direct approach, does works
let unicodeValueByValue = UnicodeScalar("\u{25a1}") // ”9633”
let c1 = Character(unicodeValueByValue) // ”a hollow square”
// B: indirect approach, this does not work
let myUnicodeString = "\u{25a1}"
let unicodeValueByVariable = UnicodeScalar(myUnicodeString) // Error: cannot find an initialiser
let c2 = Character(unicodeValueByVariable)
So, how do I display a unicode character of the format "\u{xxxx}" if it's not directly given in code?
A better way would be to use the proper \uNNNN escape sequence
for Unicode characters in JSON (see http://json.org for details).
This is automatically handled by NSJSONSerialization, and you don't
have to convert a hex code.
In your case the JSON data should be
{
"myUnicodeCharacter" : "\u25a1"
}
Here is a full self-contained example:
let jsonString = "{ \"myUnicodeCharacter\" : \"\\u25a1\"}"
println(jsonString)
// { "myUnicodeCharacter" : "\u25a1"}
let dict = NSJSONSerialization.JSONObjectWithData(jsonString.dataUsingEncoding(NSUTF8StringEncoding)!,
options: nil, error: nil) as [String : String]
let myUnicodeCharacterString = dict["myUnicodeCharacter"]!
println(myUnicodeCharacterString)
// □
I came up with a solution, which does not answer the question, but is actually a better way of doing what I'm trying to do.
The unicode character is given instead as its hexadecimal value in the JSON data file, stripping all escape characters:
{
”myUnicodeCharacter”: ”25a1”
}
Then it's processed like this, after reading the value in to myUnicodeCharacterString:
let num = Int(strtoul(myUnicodeCharacterString, nil, 16))
mySKLabelNode.Text = String(UnicodeScalar(num))
And that worked. Now the hollow square showed up.
In Swift, we can implement the following solution
let jsonString = "{ "unicodeCharacter" : "\u00BD"}"
let data = jsonString.data(using: .utf8)
if let data = data {
let dict = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: String]
print(dict?["unicodeCharacter"] ?? "")
}
Output: "½\n"