How to create JSON from a dictionary in Swift 4?

I have a JSON snipped which needs to be added as the body when I open a websocket.

 
sender: "system1@example.com", recipients:"system2@example.com", data: { text: "Test Message" },

So using Swift I did the following,


var messageDictionary : [String: Any] = [ "sender": "system1@example.com", "recipients":"system2@example.com", "data": [ "text": "Test Message" ], ] do { let jsonData = try JSONSerialization.data(withJSONObject: messageDictionary, options: .prettyPrinted) let jsonString = String(data: jsonData, encoding: String.Encoding.ascii) socket.write(string: jsonString!) print(jsonString) } catch { print(error.localizedDescription) }

When I print the jsonString, I get

 
Optional("{\n \"sender\" : \"system1@example.com\",\n \"data\" : {\n \"text\" : \"Test Message\"\n },\n \"recipients\" : \"system2@example.com\"\n}")

as the console output. I expected the above snippet to be formatted as JSON. How to get the output as normal JSON without the /n and additional spaces? Im using Swift 4 and Xcode 9.1

Edit 2:

 
let jsonData = try JSONSerialization.data(withJSONObject: messageDictionary, options: []) let decoded = try JSONSerialization.jsonObject(with: jsonData, options: [])

I tried doing the above and I get the following as the output:

 
{ data = { text = Test Message; }; recipients = "system1@example.com"; sender = "system2@example.com"; }

However the websocket expects this:

 
{ "sender":"system1@example.com","recipients": ["system2@example.com"],"data":{"text":"Test Message"}}

Even with a slight variation like misplacing of double quotes the websocket server doesnt accept the input. How to exactly format the JSOn this way so that the websocket can accept it?

Replies

You're not being careful enough with the console output, so you've obscured the fact that you're really doing this correctly. In a playground, with this code:


var messageDictionary : [String: Any] = [ "sender": "system1@example.com", "recipients":"system2@example.com", "data": [ "text": "Test Message" ], ]
let jsonData = try JSONSerialization.data(withJSONObject: messageDictionary, options: [])
let jsonString = String(data: jsonData, encoding: String.Encoding.ascii)!
print (jsonString)


I get this output:


{"sender":"system1@example.com","data":{"text":"Test Message"},"recipients":"system2@example.com"}


which AFAICT is the text you want. However, what you should do is send the data (jsonData) since that is the actual representation of the data that passes over a network. Converting to a string in order to convert it back to a stream of bytes seems unnecessary. Also, the JSON data is (presumably) UTF-8, and so trying to pass it through a conversion to ASCII can fail. (Perhaps you're restricting the data to ASCII, but this seems a bit archaic.)


The reason you got strange-looking output from your first attempt to print "jsonString" is that the variable is String?, not String, and a simple "print" displays strings and optional anythings differently. The output you got in your "Edit 2" example looks like a representation of the dictionary, not of JSON data.


Remember that a plain ol' print of some value is giving a descriptive representation of the value, mainly for debugging purposes, not an accurate reflection of the exact data contained in the value. For values with complex or voluminous internal structure, you have to take the output with a grain of salt.