objeto ejemplo dinamico diccionario crear convertir json swift dictionary nsjsonserialization

ejemplo - crear json dinamico python



¿Cómo convertir una cadena JSON a un diccionario? (7)

Detalles

  • Xcode versión 10.3 (10G8), Swift 5

Solución

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) } }

Uso

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)

Muestra de prueba

No olvides pegar el código de la solución aquí

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)") }

Registro de prueba

////////////////////////////////////////// -- 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.}

Quiero hacer una función en mi proyecto rápido que convierta String al formato json del diccionario, pero recibí un error:

No se puede convertir el tipo de expresión (@lvalue NSData, opciones: IntegerLitralConvertible ...

Este es mi código:

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 }

Hago esta función en 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; }


Con Swift 3, JSONSerialization tiene un método llamado json​Object(with:​options:​) JSONSerialization . json​Object(with:​options:​) tiene la siguiente declaración:

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

Devuelve un objeto Foundation a partir de datos JSON dados.

Cuando usas json​Object(with:​options:​) , tienes que lidiar con el manejo de errores ( try , try? O try! ) Y escribir casting (desde Any ). Por lo tanto, puede resolver su problema con uno de los siguientes patrones.

# 1 Usando un método que arroja y devuelve un tipo no opcional

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] ?? [:] }

Uso:

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 Usando un método que arroja y devuelve un tipo opcional

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] }

Uso:

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 Usar un método que no arroje y devuelva un tipo no opcional

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] ?? [:] }

Uso:

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. Usar un método que no arroje y devuelva un tipo opcional

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] }

Uso:

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


Encontré un código que convierte la cadena json a NSDictionary o NSArray. Solo agrega la extensión.

SWIFT 3.0

CÓMO UTILIZAR

let jsonData = (convertedJsonString as! String).parseJSONString

EXTENSIÓN

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 } }

}


He actualizado la respuesta de Eric D para 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 }


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 } }


Advertencia: este es un método conveniente para convertir una cadena JSON en un diccionario si, por alguna razón, tiene que trabajar desde una cadena JSON. Pero si tiene los datos JSON disponibles, debería trabajar con los datos , sin usar una cadena.

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)

Respuesta original de Swift 1:

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" }

En su versión, no pasó los parámetros adecuados a NSJSONSerialization y olvidó emitir el resultado. Además, es mejor verificar el posible error. Última nota: esto funciona solo si su valor es una Cadena. Si pudiera ser de otro tipo, sería mejor declarar la conversión del diccionario así:

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

y, por supuesto, también necesitaría cambiar el tipo de retorno de la función:

func convertStringToDictionary(text: String) -> [String:AnyObject]? { ... }


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") } }