Convert Dictionary to JSON in Swift
JsonSwiftSerializationJson Problem Overview
I have create the next Dictionary:
var postJSON = [ids[0]:answersArray[0], ids[1]:answersArray[1], ids[2]:answersArray[2]] as Dictionary
and I get:
[2: B, 1: A, 3: C]
So, how can I convert it to JSON?
Json Solutions
Solution 1 - Json
Swift 3.0
With Swift 3, the name of NSJSONSerialization
and its methods have changed, according to the Swift API Design Guidelines.
let dic = ["2": "B", "1": "A", "3": "C"]
do {
let jsonData = try JSONSerialization.data(withJSONObject: dic, options: .prettyPrinted)
// here "jsonData" is the dictionary encoded in JSON data
let decoded = try JSONSerialization.jsonObject(with: jsonData, options: [])
// here "decoded" is of type `Any`, decoded from JSON data
// you can now cast it with the right type
if let dictFromJSON = decoded as? [String:String] {
// use dictFromJSON
}
} catch {
print(error.localizedDescription)
}
Swift 2.x
do {
let jsonData = try NSJSONSerialization.dataWithJSONObject(dic, options: NSJSONWritingOptions.PrettyPrinted)
// here "jsonData" is the dictionary encoded in JSON data
let decoded = try NSJSONSerialization.JSONObjectWithData(jsonData, options: [])
// here "decoded" is of type `AnyObject`, decoded from JSON data
// you can now cast it with the right type
if let dictFromJSON = decoded as? [String:String] {
// use dictFromJSON
}
} catch let error as NSError {
print(error)
}
Swift 1
var error: NSError?
if let jsonData = NSJSONSerialization.dataWithJSONObject(dic, options: NSJSONWritingOptions.PrettyPrinted, error: &error) {
if error != nil {
println(error)
} else {
// here "jsonData" is the dictionary encoded in JSON data
}
}
if let decoded = NSJSONSerialization.JSONObjectWithData(jsonData, options: nil, error: &error) as? [String:String] {
if error != nil {
println(error)
} else {
// here "decoded" is the dictionary decoded from JSON data
}
}
Solution 2 - Json
You are making a wrong assumption. Just because the debugger/Playground shows your dictionary in square brackets (which is how Cocoa displays dictionaries) that does not mean that is the way the JSON output is formatted.
Here is example code that will convert a dictionary of strings to JSON:
Swift 3 version:
import Foundation
let dictionary = ["aKey": "aValue", "anotherKey": "anotherValue"]
if let theJSONData = try? JSONSerialization.data(
withJSONObject: dictionary,
options: []) {
let theJSONText = String(data: theJSONData,
encoding: .ascii)
print("JSON string = \(theJSONText!)")
}
To display the above in "pretty printed" format you'd change the options line to:
options: [.prettyPrinted]
Or in Swift 2 syntax:
import Foundation
let dictionary = ["aKey": "aValue", "anotherKey": "anotherValue"]
let theJSONData = NSJSONSerialization.dataWithJSONObject(
dictionary ,
options: NSJSONWritingOptions(0),
error: nil)
let theJSONText = NSString(data: theJSONData!,
encoding: NSASCIIStringEncoding)
println("JSON string = \(theJSONText!)")
The output of that is
"JSON string = {"anotherKey":"anotherValue","aKey":"aValue"}"
Or in pretty format:
{
"anotherKey" : "anotherValue",
"aKey" : "aValue"
}
The dictionary is enclosed in curly braces in the JSON output, just as you'd expect.
EDIT:
In Swift 3/4 syntax, the code above looks like this:
let dictionary = ["aKey": "aValue", "anotherKey": "anotherValue"]
if let theJSONData = try? JSONSerialization.data(
withJSONObject: dictionary,
options: .prettyPrinted
),
let theJSONText = String(data: theJSONData,
encoding: String.Encoding.ascii) {
print("JSON string = \n\(theJSONText)")
}
}
Solution 3 - Json
Swift 5:
let dic = ["2": "B", "1": "A", "3": "C"]
let encoder = JSONEncoder()
if let jsonData = try? encoder.encode(dic) {
if let jsonString = String(data: jsonData, encoding: .utf8) {
print(jsonString)
}
}
Note that keys and values must implement Codable
. Strings, Ints, and Doubles (and more) are already Codable
. See Encoding and Decoding Custom Types.
Also note: As mentioned in a comment, Any
does not conform to Codable
. It is likely still a good approach to adapt your data to become Codable
so that you are making use of Swift typing (especially in the case that you are also going to decode any encoded json), and so that you can be more declarative about the outcome of your encoding.
Solution 4 - Json
My answer for your question is below
let dict = ["0": "ArrayObjectOne", "1": "ArrayObjecttwo", "2": "ArrayObjectThree"]
var error : NSError?
let jsonData = try! NSJSONSerialization.dataWithJSONObject(dict, options: NSJSONWritingOptions.PrettyPrinted)
let jsonString = NSString(data: jsonData, encoding: String.Encoding.utf8.rawValue)! as String
print(jsonString)
Answer is
{
"0" : "ArrayObjectOne",
"1" : "ArrayObjecttwo",
"2" : "ArrayObjectThree"
}
Solution 5 - Json
Swift 4 Dictionary
extension.
extension Dictionary {
var jsonStringRepresentation: String? {
guard let theJSONData = try? JSONSerialization.data(withJSONObject: self,
options: [.prettyPrinted]) else {
return nil
}
return String(data: theJSONData, encoding: .ascii)
}
}
Solution 6 - Json
Sometimes it's necessary to print out server's response for debugging purposes. Here's a function I use:
extension Dictionary {
var json: String {
let invalidJson = "Not a valid JSON"
do {
let jsonData = try JSONSerialization.data(withJSONObject: self, options: .prettyPrinted)
return String(bytes: jsonData, encoding: String.Encoding.utf8) ?? invalidJson
} catch {
return invalidJson
}
}
func printJson() {
print(json)
}
}
Example of use:
(lldb) po dictionary.printJson()
{
"InviteId" : 2,
"EventId" : 13591,
"Messages" : [
{
"SenderUserId" : 9514,
"MessageText" : "test",
"RecipientUserId" : 9470
},
{
"SenderUserId" : 9514,
"MessageText" : "test",
"RecipientUserId" : 9470
}
],
"TargetUserId" : 9470,
"InvitedUsers" : [
9470
],
"InvitingUserId" : 9514,
"WillGo" : true,
"DateCreated" : "2016-08-24 14:01:08 +00:00"
}
Solution 7 - Json
Swift 5:
extension Dictionary {
/// Convert Dictionary to JSON string
/// - Throws: exception if dictionary cannot be converted to JSON data or when data cannot be converted to UTF8 string
/// - Returns: JSON string
func toJson() throws -> String {
let data = try JSONSerialization.data(withJSONObject: self)
if let string = String(data: data, encoding: .utf8) {
return string
}
throw NSError(domain: "Dictionary", code: 1, userInfo: ["message": "Data cannot be converted to .utf8 string"])
}
}
Solution 8 - Json
Swift 3:
let jsonData = try? JSONSerialization.data(withJSONObject: dict, options: [])
let jsonString = String(data: jsonData!, encoding: .utf8)!
print(jsonString)
Solution 9 - Json
Answer for your question is below:
Swift 2.1
do {
if let postData : NSData = try NSJSONSerialization.dataWithJSONObject(dictDataToBeConverted, options: NSJSONWritingOptions.PrettyPrinted){
let json = NSString(data: postData, encoding: NSUTF8StringEncoding)! as String
print(json)}
}
catch {
print(error)
}
Solution 10 - Json
In Swift 5.4
extension Dictionary {
var jsonData: Data? {
return try? JSONSerialization.data(withJSONObject: self, options: [.prettyPrinted])
}
func toJSONString() -> String? {
if let jsonData = jsonData {
let jsonString = String(data: jsonData, encoding: .utf8)
return jsonString
}
return nil
}
}
The idea of having it as a variable is because then you can reuse it like that:
extension Dictionary {
func decode<T:Codable>() throws -> T {
return try JSONDecoder().decode(T.self, from: jsonData ?? Data())
}
}
Solution 11 - Json
Here's an easy extension to do this:
https://gist.github.com/stevenojo/0cb8afcba721838b8dcb115b846727c3
extension Dictionary {
func jsonString() -> NSString? {
let jsonData = try? JSONSerialization.data(withJSONObject: self, options: [])
guard jsonData != nil else {return nil}
let jsonString = String(data: jsonData!, encoding: .utf8)
guard jsonString != nil else {return nil}
return jsonString! as NSString
}
}
Solution 12 - Json
using lldb
(lldb) p JSONSerialization.data(withJSONObject: notification.request.content.userInfo, options: [])
(Data) $R16 = 375 bytes
(lldb) p String(data: $R16!, encoding: .utf8)!
(String) $R18 = "{\"aps\": \"some_text\"}"
//or
p String(data: JSONSerialization.data(withJSONObject: notification.request.content.userInfo, options: [])!, encoding: .utf8)!
(String) $R4 = "{\"aps\": \"some_text\"}"
Solution 13 - Json
This works for me:
import SwiftyJSON
extension JSON {
mutating func appendIfKeyValuePair(key: String, value: Any){
if var dict = self.dictionaryObject {
dict[key] = value
self = JSON(dict)
}
}
}
Usage:
var data: JSON = []
data.appendIfKeyValuePair(key: "myKey", value: "myValue")
Solution 14 - Json
private func convertDictToJson(dict : NSDictionary) -> NSDictionary?
{
var jsonDict : NSDictionary!
do {
let jsonData = try JSONSerialization.data(withJSONObject:dict, options:[])
let jsonDataString = String(data: jsonData, encoding: String.Encoding.utf8)!
print("Post Request Params : \(jsonDataString)")
jsonDict = [ParameterKey : jsonDataString]
return jsonDict
} catch {
print("JSON serialization failed: \(error)")
jsonDict = nil
}
return jsonDict
}