Convert NSString to JSON - ios

I am converting a [NSDictionary] to NSString like so :
do{
let newDict = try NSJSONSerialization.dataWithJSONObject(objectDictionaries, options: NSJSONWritingOptions.PrettyPrinted)
if let json = NSString(data: newDict, encoding: NSUTF8StringEncoding) {
print(json)
}
When the json prints out I get this:
How do I convert this NSString to JSON without changing the format as this photo shows?
The I want to send this json to a API and the format I want is the only one the API will be able to encode,

Remove the option NSJSONWritingOptions.PrettyPrinted in the call to dataWithJSONObject. That is what is forcing the outputted string to be formatted like that.

The output of NSJSONSerialization.dataWithJSONObject is valid JSON, and that's what you should send to an API. Conversion to a string is pointless unless you want to view the output for debugging purposes.
NSJSONWritingOptions.PrettyPrinted is useful if you want to view the output for debugging purposes, but otherwise it's just a waste of time and makes the JSON a few percent bigger which takes memory, time to send to the API, time to process in the API.
PS. If "Pretty printed" or not makes any difference to your API, then your API is pretty badly broken.

Related

Swift: write JSON and save to iPhone File locally

I am learning how to write JSON format data to an iPhone. So with one button clicked, I want to save those data to the iPhone. I looked a simple look on how to write some simple text and saved it to the iPhone file and it worked. However, I tried to apply the same idea to JSON data but still haven't figure out. I tried:
Rather than having contents equal to some written text, I tried to put it as my data (jsondata).
But it does not seem working with
try jsondata.write(to: fileURL, atomically: false, encoding: .utf8)
#IBAction func writeFiles(_ sender: Any) {
let file = "\(UUID().uuidString).txt"
let contents = "Testing"
let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let fileURL = dir.appendingPathComponent(file)
do {
try contents.write(to: fileURL, atomically: false, encoding: .utf8)
}
catch {
print("Error: \(error)")
}
}
Sorry I am a bit new and learning Swift at the moment
Thanks!
Here is a simple project for you to clone or browse the source files
https://github.com/eSpecialized/WriteJsonToFiles
The View Controller contains the example;
https://github.com/eSpecialized/WriteJsonToFiles/blob/master/WriteToFiles/ViewController.swift
Basically you need to do a few steps for writing;
Assemble your objects (Strings etc).
Convert to JSONEncoded Data using the JSONEncoder.
The actual 'Data' Object can write it's binary content to storage.
To read the data;
You need a JSONDecoder.
You need the FileContents in memory using Data(contents:...)
Decode the in-memory data back into the object like it was stored.
A more complicated example of reading and writing JSON to a Web Service API is on Medium here > https://medium.com/better-programming/json-parsing-in-swift-2498099b78f
The concepts are the same, the destination changes from a file in the users document folder to a web service API. I feel that it is adequate to get you started with reading and writing JSON.
The Medium article goes a step further with introducing you to Data Models and reading and writing those Data Model Structs using the Codable protocol.
Enjoy! :)

How do I POST raw NSData as well as some NSStrings to my server?

I have a large piece of NSData I want to send to my server, but I also want to send a string dictionary of string keys mapped to string keys.
How do I POST both in the same request?
Almost all guides show wrapping it in an NSDictionary then using NSJSONSerialization to turn it into NSData then POST that, but I can't have NSData and NSStrings in the same NSDictionary it just crashes, so I assume I have to keep it separate, but how would that look?
Essentially how do I serialize JSON into NSData and then also have a separate NSData blob with it?
let body = NSMutableDictionary()
body.setValue("myString" forKey: "stringType")
body.setValue(data?.base64EncodedString(options: .lineLength64Characters) forKey: "dataType")
In this way you can have both data and string in the dictionary.
Here 'data?.base64EncodedString(options: .lineLength64Characters)' returns you a string with base64 encoding. So your dictionary contains only string and at server end you have to covert it back to data.
Hope it solves your issue

swift gzip data to string issue

I use gzip library to convert data to gzip data
If I want to get string from data I do String(data: data, encoding: .utf8) . But if I do the same for gzip data I get nil string, because as far as I understand it's impossible to convert gzip data to string with .utf8 encoding.
I need that because I want to compare data with a server developer (because he sometimes he says that my data is incorrect format, but sometimes it's ok, and that's strange because I use the same library, and I have thoughts that may be the problem is on server side).
Is there any way to convert gzip data to any string to compare it then later?
If this is just for debug purpose, then I think the quickest way is:
let myGZipNSData = myGZipData as! NSData //I wrote a "!" just for the sample)
print("myGZipNSData: \(myGZipNSData)")
It should output:
myGZipNSData: <5b226d79 41727261 7956616c 75653022 2c226d79 41727261 7956616c 75653122 5d>
This relies on -description method of NSData which print "<hexValue>".
Do not rely on it on release version, almost never rely on -description (yes, Apple could change the behavior of -description in next release. It happened on a different class).
Other way (safer) to get almost the same result, you can check this question: How to convert Data to hex string in swift which you get you the same result (almost, less space, and no </>) as the previous one.
Other way: Base 64
Use base64EncodedString() method of Data:
let base64Str = myGZipData?.base64EncodedString()
print("base64Str: \(base64Str!)")
Output:
base64Str: WyJteUFycmF5VmFsdWUwIiwibXlBcnJheVZhbHVlMSJd
Now, there should be other way:
Have a array representation with Int values (between 0/255 instead of hex), but it seems to be for debug purpose so check if you can "reproduce the current solutions" (working/fast implementation) I gave you, and check with the server developer what he/she can do on his/her side too to compare.
Note:
For the purpose of this sample, myGZipData is constructed this way:
let array = ["myArrayValue0", "myArrayValue1"]
let myGZipData = try? JSONSerialization.data(withJSONObject: array, options:[])
It's not really a GZipData, but the goal was to quickly have a Data object "big enough".

Set a UIImageView's Image based on Binary Data

I have an image I'm trying to load from a web service. I've tested the data I got from the web service by adding data:image/gif;base64, before it and entering it as a URL in Chrome and the image loaded perfectly.
In my iOS app, I tried profilePic.image = UIImage.init(data: picData.data(using: .utf8)!) where picData is a string with the contents I tested above, however nothing loaded.
I get the feeling what I did wrong is somewhere in picData.data(using: .utf8)!) but I'm not sure. Any suggestions?
In case it helps, here's the binary data I'm working with: https://pastebin.com/xiWHaPB6
UTF-8 is an encoding for Unicode Strings not arbitrary 8 bit data!
Your if the mime type you've shown is accurate, the data is a Base64 encoded string. The first thing you want to do is convert that string to an unencoded, binary form. Then try creating your UIImage from that:
let unencodedData = Data(base64Encoded: picData)
let image = UIImage(data: unencodedData)

Reading Websites in iOS

I am trying to read data from my API. I am not using JSON data because the API doesn't return an array, just a line of text. Anyways, I am using the following code to read the text from the API.
func contactVetApi(url:String){
let nsUrl = NSURL(string:url)
let task = NSURLSession.sharedSession().dataTaskWithURL(nsUrl!){
(data, response, error) in
print(data)
}
task.resume()
}
I am calling this function in the ViewDidLoad function of my ViewController file. As you can see, it takes a parameter that is a string. The parameter is the URL to read. It then translates the string into a NSUrl so it can be used with the sharedSession. I then initialize the shared session and create a data task with that url. I then print out the data it returns. The only issue is that the output isn't what I am expecting. What I am expecting is for it to say, "Future home of something quite cool." Although, this is what I am getting.
Optional(<46757475 72652068 6f6d6520 6f662073 6f6d6574 68696e67 20717569 74652063 6f6f6c>)
Optional(<46757475 72652068 6f6d6520 6f662073 6f6d6574 68696e67 20717569 74652063 6f6f6c>)
I need help figuring out why it is printing that out instead of what I am expecting. In case it is needed, the api url is http://apis.wilsonfamily5.org/vet/about.php. Before anybody asks though, I did add into the info.plist file the disabling of the iOS 9 app transport security. If you need any extra information to help me solve this problem, I would be more then happy to give it to you. I want to thank you in advance.
You currently are printing a NSData object, which will always look like that jibberish. What you actually want however is to convert the NSData to a NSString or String to create a human readable form:
var dataAsString = NSString(data: data, encoding: NSUTF8StringEncoding)
Taken from this answer.

Resources