How to convert a JSON string to a dictionary?

I want to make one function in my quick project that converts String to json Dictionary format, but I have one error:

Cannot convert expression type (@lvalue NSData, options: IntegerLitralConvertible ...

This is my code:

func convertStringToDictionary (text:String) -> Dictionary<String,String> { var data :NSData = text.dataUsingEncoding(NSUTF8StringEncoding)! var json :Dictionary = NSJSONSerialization.JSONObjectWithData(data, options:0, error: nil) return json } 

I do this function in Objective-C:

 - (NSDictionary*)convertStringToDictionary:(NSString*)string { NSError* error; //giving error as it takes dic, array,etc only. not custom object. NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding]; id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; return json; } 
+148
json dictionary swift nsjsonserialization
May 27 '15 at 11:05
source share
7 answers

Warning: this is a convenient method of converting a JSON string to a dictionary, if for some reason you have to work from a JSON string. But if you have JSON data , you should instead work with the data without using any string.

Swift 3

 func convertToDictionary(text: String) -> [String: Any]? { if let data = text.data(using: .utf8) { do { return try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] } catch { print(error.localizedDescription) } } return nil } let str = "{\"name\":\"James\"}" let dict = convertToDictionary(text: str) 

Swift 2

 func convertStringToDictionary(text: String) -> [String:AnyObject]? { if let data = text.dataUsingEncoding(NSUTF8StringEncoding) { do { return try NSJSONSerialization.JSONObjectWithData(data, options: []) as? [String:AnyObject] } catch let error as NSError { print(error) } } return nil } let str = "{\"name\":\"James\"}" let result = convertStringToDictionary(str) 

Original Swift 1 answer:

 func convertStringToDictionary(text: String) -> [String:String]? { if let data = text.dataUsingEncoding(NSUTF8StringEncoding) { var error: NSError? let json = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.allZeros, error: &error) as? [String:String] if error != nil { println(error) } return json } return nil } let str = "{\"name\":\"James\"}" let result = convertStringToDictionary(str) // ["name": "James"] if let name = result?["name"] { // The `?` is here because our `convertStringToDictionary` function returns an Optional println(name) // "James" } 

In your version, you did not pass the correct NSJSONSerialization parameters and forgot to make a result. In addition, it is better to check for a possible error. Last note: this only works if your value is a string. If it could be a different type, it would be better to declare a dictionary conversion as follows:

 let json = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.allZeros, error: &error) as? [String:AnyObject] 

and of course, you will also need to change the return type of the function:

 func convertStringToDictionary(text: String) -> [String:AnyObject]? { ... } 
+341
May 27 '15 at 11:11
source share

I updated Eric D for Swift 2 :

 func convertStringToDictionary(text: String) -> [String:AnyObject]? { if let data = text.dataUsingEncoding(NSUTF8StringEncoding) { do { let json = try NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers) as? [String:AnyObject] return json } catch { print("Something went wrong") } } return nil } 
+50
Oct. 16 '15 at 2:39
source share

Swift 3 :

 if let data = text.data(using: String.Encoding.utf8) { do { let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String:Any] print(json) } catch { print("Something went wrong") } } 
+22
Dec 23 '16 at 17:39
source share

In Swift 3, JSONSerialization has a method called json​Object(with:​options:​) JSONSerialization . json​Object(with:​options:​) has the following declaration:

 class func jsonObject(with data: Data, options opt: JSONSerialization.ReadingOptions = []) throws -> Any 

Returns a Foundation object from JSON data.

When you use json​Object(with:​options:​) , you have to deal with error handling ( try , try? Or try! ) And type casting (from Any ). Thus, you can solve your problem using one of the following templates.




# 1. Using a method that throws and returns an optional type

 import Foundation func convertToDictionary(from text: String) throws -> [String: String] { guard let data = text.data(using: .utf8) else { return [:] } let anyResult: Any = try JSONSerialization.jsonObject(with: data, options: []) return anyResult as? [String: String] ?? [:] } 

Using:

 let string1 = "{\"City\":\"Paris\"}" do { let dictionary = try convertToDictionary(from: string1) print(dictionary) // prints: ["City": "Paris"] } catch { print(error) } 
 let string2 = "{\"Quantity\":100}" do { let dictionary = try convertToDictionary(from: string2) print(dictionary) // prints [:] } catch { print(error) } 
 let string3 = "{\"Object\"}" do { let dictionary = try convertToDictionary(from: string3) print(dictionary) } catch { print(error) // prints: Error Domain=NSCocoaErrorDomain Code=3840 "No value for key in object around character 9." UserInfo={NSDebugDescription=No value for key in object around character 9.} } 



# 2. Using a method that throws and returns an optional type

 import Foundation func convertToDictionary(from text: String) throws -> [String: String]? { guard let data = text.data(using: .utf8) else { return [:] } let anyResult: Any = try JSONSerialization.jsonObject(with: data, options: []) return anyResult as? [String: String] } 

Using:

 let string1 = "{\"City\":\"Paris\"}" do { let dictionary = try convertToDictionary(from: string1) print(String(describing: dictionary)) // prints: Optional(["City": "Paris"]) } catch { print(error) } 
 let string2 = "{\"Quantity\":100}" do { let dictionary = try convertToDictionary(from: string2) print(String(describing: dictionary)) // prints nil } catch { print(error) } 
 let string3 = "{\"Object\"}" do { let dictionary = try convertToDictionary(from: string3) print(String(describing: dictionary)) } catch { print(error) // prints: Error Domain=NSCocoaErrorDomain Code=3840 "No value for key in object around character 9." UserInfo={NSDebugDescription=No value for key in object around character 9.} } 



# 3. Using a method that does not throw and returns an optional type

 import Foundation func convertToDictionary(from text: String) -> [String: String] { guard let data = text.data(using: .utf8) else { return [:] } let anyResult: Any? = try? JSONSerialization.jsonObject(with: data, options: []) return anyResult as? [String: String] ?? [:] } 

Using:

 let string1 = "{\"City\":\"Paris\"}" let dictionary1 = convertToDictionary(from: string1) print(dictionary1) // prints: ["City": "Paris"] 
 let string2 = "{\"Quantity\":100}" let dictionary2 = convertToDictionary(from: string2) print(dictionary2) // prints: [:] 
 let string3 = "{\"Object\"}" let dictionary3 = convertToDictionary(from: string3) print(dictionary3) // prints: [:] 



# 4. Using a method that does not throw and returns an optional type

 import Foundation func convertToDictionary(from text: String) -> [String: String]? { guard let data = text.data(using: .utf8) else { return nil } let anyResult = try? JSONSerialization.jsonObject(with: data, options: []) return anyResult as? [String: String] } 

Using:

 let string1 = "{\"City\":\"Paris\"}" let dictionary1 = convertToDictionary(from: string1) print(String(describing: dictionary1)) // prints: Optional(["City": "Paris"]) 
 let string2 = "{\"Quantity\":100}" let dictionary2 = convertToDictionary(from: string2) print(String(describing: dictionary2)) // prints: nil 
 let string3 = "{\"Object\"}" let dictionary3 = convertToDictionary(from: string3) print(String(describing: dictionary3)) // prints: nil 
+12
Mar 29 '17 at 15:04
source share

Swift 4

 extension String { func convertToDictionary() -> [String: Any]? { if let data = self.data(using: .utf8) { do { return try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] } catch { print(error.localizedDescription) } } return nil } } 
+6
12 Sep '18 at 13:46
source share

I found code that converts a JSON string to an NSDictionary or NSArray. Just add the extension.

SWIFT 3.0

HOW TO USE

 let jsonData = (convertedJsonString as! String).parseJSONString 

SPREAD

 extension String { var parseJSONString: AnyObject? { let data = self.data(using: String.Encoding.utf8, allowLossyConversion: false) if let jsonData = data { // Will return an object or nil if JSON decoding fails do { let message = try JSONSerialization.jsonObject(with: jsonData, options:.mutableContainers) if let jsonResult = message as? NSMutableArray { return jsonResult //Will return the json array output } else if let jsonResult = message as? NSMutableDictionary { return jsonResult //Will return the json dictionary output } else { return nil } } catch let error as NSError { print("An error occurred: \(error)") return nil } } else { // Lossless conversion of the string was not possible return nil } } 

}

+2
Apr 21 '17 at 12:46 on
source share

More details

  • Xcode Version 10.3 (10G8), Swift 5

Decision

 import Foundation // MARK: - CastingError struct CastingError: Error { let fromType: Any.Type let toType: Any.Type init<FromType, ToType>(fromType: FromType.Type, toType: ToType.Type) { self.fromType = fromType self.toType = toType } } extension CastingError: LocalizedError { var localizedDescription: String { return "Can not cast from \(fromType) to \(toType)" } } extension CastingError: CustomStringConvertible { var description: String { return localizedDescription } } // MARK: - Data cast extensions extension Data { func toDictionary(options: JSONSerialization.ReadingOptions = []) throws -> [String: Any] { return try to(type: [String: Any].self, options: options) } func to<T>(type: T.Type, options: JSONSerialization.ReadingOptions = []) throws -> T { guard let result = try JSONSerialization.jsonObject(with: self, options: options) as? T else { throw CastingError(fromType: type, toType: T.self) } return result } } // MARK: - String cast extensions extension String { func asJSON<T>(to type: T.Type, using encoding: String.Encoding = .utf8) throws -> T { guard let data = data(using: encoding) else { throw CastingError(fromType: type, toType: T.self) } return try data.to(type: T.self) } func asJSONToDictionary(using encoding: String.Encoding = .utf8) throws -> [String: Any] { return try asJSON(to: [String: Any].self, using: encoding) } } // MARK: - Dictionary cast extensions extension Dictionary { func toData(options: JSONSerialization.WritingOptions = []) throws -> Data { return try JSONSerialization.data(withJSONObject: self, options: options) } } 

Usage

Usage
 let value1 = try? data.toDictionary() let value2 = try? data.to(type: [String: Any].self) let value3 = try? data.to(type: [String: String].self) let value4 = try? string.asJSONToDictionary() let value5 = try? string.asJSON(to: [String: String].self) 

Test sample

Remember to insert the solution code here.

 func testDescriber(text: String, value: Any) { print("\n//////////////////////////////////////////") print("-- \(text)\n\n type: \(type(of: value))\n value: \(value)") } let json1: [String: Any] = ["key1" : 1, "key2": true, "key3" : ["a": 1, "b": 2], "key4": [1,2,3]] var jsonData = try? json1.toData() testDescriber(text: "Sample test of func toDictionary()", value: json1) if let data = jsonData { print(" Result: \(String(describing: try? data.toDictionary()))") } testDescriber(text: "Sample test of func to<T>() -> [String: Any]", value: json1) if let data = jsonData { print(" Result: \(String(describing: try? data.to(type: [String: Any].self)))") } testDescriber(text: "Sample test of func to<T>() -> [String] with cast error", value: json1) if let data = jsonData { do { print(" Result: \(String(describing: try data.to(type: [String].self)))") } catch { print(" ERROR: \(error)") } } let array = [1,4,5,6] testDescriber(text: "Sample test of func to<T>() -> [Int]", value: array) if let data = try? JSONSerialization.data(withJSONObject: array) { print(" Result: \(String(describing: try? data.to(type: [Int].self)))") } let json2 = ["key1": "a", "key2": "b"] testDescriber(text: "Sample test of func to<T>() -> [String: String]", value: json2) if let data = try? JSONSerialization.data(withJSONObject: json2) { print(" Result: \(String(describing: try? data.to(type: [String: String].self)))") } let jsonString = "{\"key1\": \"a\", \"key2\": \"b\"}" testDescriber(text: "Sample test of func to<T>() -> [String: String]", value: jsonString) print(" Result: \(String(describing: try? jsonString.asJSON(to: [String: String].self)))") testDescriber(text: "Sample test of func to<T>() -> [String: String]", value: jsonString) print(" Result: \(String(describing: try? jsonString.asJSONToDictionary()))") let wrongJsonString = "{\"key1\": \"a\", \"key2\":}" testDescriber(text: "Sample test of func to<T>() -> [String: String] with JSONSerialization error", value: jsonString) do { let json = try wrongJsonString.asJSON(to: [String: String].self) print(" Result: \(String(describing: json))") } catch { print(" ERROR: \(error)") } 

Test log

 ////////////////////////////////////////// -- Sample test of func toDictionary() type: Dictionary<String, Any> value: ["key4": [1, 2, 3], "key2": true, "key3": ["a": 1, "b": 2], "key1": 1] Result: Optional(["key4": <__NSArrayI 0x600002a35380>( 1, 2, 3 ) , "key2": 1, "key3": { a = 1; b = 2; }, "key1": 1]) ////////////////////////////////////////// -- Sample test of func to<T>() -> [String: Any] type: Dictionary<String, Any> value: ["key4": [1, 2, 3], "key2": true, "key3": ["a": 1, "b": 2], "key1": 1] Result: Optional(["key4": <__NSArrayI 0x600002a254d0>( 1, 2, 3 ) , "key2": 1, "key1": 1, "key3": { a = 1; b = 2; }]) ////////////////////////////////////////// -- Sample test of func to<T>() -> [String] with cast error type: Dictionary<String, Any> value: ["key4": [1, 2, 3], "key2": true, "key3": ["a": 1, "b": 2], "key1": 1] ERROR: Can not cast from Array<String> to Array<String> ////////////////////////////////////////// -- Sample test of func to<T>() -> [Int] type: Array<Int> value: [1, 4, 5, 6] Result: Optional([1, 4, 5, 6]) ////////////////////////////////////////// -- Sample test of func to<T>() -> [String: String] type: Dictionary<String, String> value: ["key1": "a", "key2": "b"] Result: Optional(["key1": "a", "key2": "b"]) ////////////////////////////////////////// -- Sample test of func to<T>() -> [String: String] type: String value: {"key1": "a", "key2": "b"} Result: Optional(["key1": "a", "key2": "b"]) ////////////////////////////////////////// -- Sample test of func to<T>() -> [String: String] type: String value: {"key1": "a", "key2": "b"} Result: Optional(["key1": a, "key2": b]) ////////////////////////////////////////// -- Sample test of func to<T>() -> [String: String] with JSONSerialization error type: String value: {"key1": "a", "key2": "b"} ERROR: Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 21." UserInfo={NSDebugDescription=Invalid value around character 21.} 
0
Aug 20 '19 at 16:06
source share



All Articles