Comprende el código bien previamente a usarlo a tu trabajo y si tquieres aportar algo puedes decirlo en los comentarios.
Solución:
Con algo de inspiración de esta esencia que encontré, escribí algunas extensiones para UnkeyedDecodingContainer
y KeyedDecodingContainer
. Puede encontrar un enlace a mi esencia aquí. Al usar este código, ahora puede decodificar cualquier Array
o Dictionary
con la sintaxis familiar:
let dictionary: [String: Any] = try container.decode([String: Any].self, forKey: key)
o
let array: [Any] = try container.decode([Any].self, forKey: key)
Editar: Hay una salvedad que he encontrado que es decodificar un array de diccionarios [[String: Any]]
La sintaxis requerida es la siguiente. Es probable que desee lanzar un error en lugar de forzar el lanzamiento:
let items: [[String: Any]] = try container.decode(Array.self, forKey: .items) as! [[String: Any]]
EDITAR 2: Si simplemente desea convertir un archivo completo en un diccionario, es mejor que se quede con la API de JSONSerialization, ya que no he descubierto una manera de extender JSONDecoder para decodificar directamente un diccionario.
guard let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else
// appropriate error handling
return
Las extensiones
// Inspired by https://gist.github.com/mbuchetics/c9bc6c22033014aa0c550d3b4324411a
struct JSONCodingKeys: CodingKey
var stringValue: String
init?(stringValue: String)
self.stringValue = stringValue
var intValue: Int?
init?(intValue: Int)
self.init(stringValue: "(intValue)")
self.intValue = intValue
extension KeyedDecodingContainer
func decode(_ type: Dictionary.Type, forKey key: K) throws -> Dictionary
let container = try self.nestedContainer(keyedBy: JSONCodingKeys.self, forKey: key)
return try container.decode(type)
func decodeIfPresent(_ type: Dictionary.Type, forKey key: K) throws -> Dictionary?
guard contains(key) else
return nil
guard try decodeNil(forKey: key) == false else
return nil
return try decode(type, forKey: key)
func decode(_ type: Array.Type, forKey key: K) throws -> Array
var container = try self.nestedUnkeyedContainer(forKey: key)
return try container.decode(type)
func decodeIfPresent(_ type: Array.Type, forKey key: K) throws -> Array?
guard contains(key) else
return nil
guard try decodeNil(forKey: key) == false else
return nil
return try decode(type, forKey: key)
func decode(_ type: Dictionary.Type) throws -> Dictionary
var dictionary = Dictionary()
for key in allKeys
if let boolValue = try? decode(Bool.self, forKey: key)
dictionary[key.stringValue] = boolValue
else if let stringValue = try? decode(String.self, forKey: key)
dictionary[key.stringValue] = stringValue
else if let intValue = try? decode(Int.self, forKey: key)
dictionary[key.stringValue] = intValue
else if let doubleValue = try? decode(Double.self, forKey: key)
dictionary[key.stringValue] = doubleValue
else if let nestedDictionary = try? decode(Dictionary.self, forKey: key)
dictionary[key.stringValue] = nestedDictionary
else if let nestedArray = try? decode(Array.self, forKey: key)
dictionary[key.stringValue] = nestedArray
return dictionary
extension UnkeyedDecodingContainer
mutating func decode(_ type: Array.Type) throws -> Array
var array: [Any] = []
while isAtEnd == false
// See if the current value in the JSON array is `null` first and prevent infite recursion with nested arrays.
if try decodeNil()
continue
else if let value = try? decode(Bool.self)
array.append(value)
else if let value = try? decode(Double.self)
array.append(value)
else if let value = try? decode(String.self)
array.append(value)
else if let nestedDictionary = try? decode(Dictionary.self)
array.append(nestedDictionary)
else if let nestedArray = try? decode(Array.self)
array.append(nestedArray)
return array
mutating func decode(_ type: Dictionary.Type) throws -> Dictionary
let nestedContainer = try self.nestedContainer(keyedBy: JSONCodingKeys.self)
return try nestedContainer.decode(type)
También jugué con este problema y finalmente escribí una biblioteca simple para trabajar con tipos “JSON genéricos”. (Donde “genérico” significa “sin estructura conocida de antemano”.) El punto principal es representar el JSON genérico con un tipo concreto:
public enum JSON
case string(String)
case number(Float)
case object([String:JSON])
case array([JSON])
case bool(Bool)
case null
Este tipo puede implementar Codable
y Equatable
.
Puede crear una estructura de metadatos que confirme Decodable
protocolo y uso JSONDecoder
clase para crear objetos a partir de datos utilizando el método de decodificación como se muestra a continuación
let json: [String: Any] = [
"object": "customer",
"id": "4yq6txdpfadhbaqnwp3",
"email": "[email protected]",
"metadata": [
"link_id": "linked-id",
"buy_count": 4
]
]
struct Customer: Decodable
let object: String
let id: String
let email: String
let metadata: Metadata
struct Metadata: Decodable
let link_id: String
let buy_count: Int
let data = try JSONSerialization.data(withJSONObject: json, options: .prettyPrinted)
let decoder = JSONDecoder()
do
let customer = try decoder.decode(Customer.self, from: data)
print(customer)
catch
print(error.localizedDescription)
Reseñas y calificaciones del artículo
Si sostienes algún titubeo y capacidad de acrecentar nuestro tutorial te insinuamos realizar una ilustración y con placer lo observaremos.