Swift Language Serialización, codificación y decodificación JSON con Apple Foundation y Swift Standard Library


Ejemplo

La clase JSONSerialization está integrada en el marco de la Fundación de Apple.

2.2

Leer json

La función JSONObjectWithData toma NSData y devuelve AnyObject . Se puede usar as? para convertir el resultado a su tipo esperado.

do {
    guard let jsonData = "[\"Hello\", \"JSON\"]".dataUsingEncoding(NSUTF8StringEncoding) else {
        fatalError("couldn't encode string as UTF-8")
    }

    // Convert JSON from NSData to AnyObject
    let jsonObject = try NSJSONSerialization.JSONObjectWithData(jsonData, options: [])
    
    // Try to convert AnyObject to array of strings
    if let stringArray = jsonObject as? [String] {
        print("Got array of strings: \(stringArray.joinWithSeparator(", "))")
    }
} catch {
    print("error reading JSON: \(error)")
}

Puede pasar las options: .AllowFragments que se options: .AllowFragments lugar de las options: [] para permitir la lectura de JSON cuando el objeto de nivel superior no es una matriz o diccionario.

Escribir json

Al llamar a dataWithJSONObject convierte un objeto compatible con JSON (matrices anidadas o diccionarios con cadenas, números y NSNull ) en NSData bruto codificados como UTF-8.

do {
    // Convert object to JSON as NSData
    let jsonData = try NSJSONSerialization.dataWithJSONObject(jsonObject, options: [])
    print("JSON data: \(jsonData)")
    
    // Convert NSData to String
    let jsonString = String(data: jsonData, encoding: NSUTF8StringEncoding)!
    print("JSON string: \(jsonString)")
} catch {
    print("error writing JSON: \(error)")
}

Puede pasar las options: .PrettyPrinted lugar de las options: [] para impresión bonita.

3.0

Mismo comportamiento en Swift 3 pero con una sintaxis diferente.

do {
    guard let jsonData = "[\"Hello\", \"JSON\"]".data(using: String.Encoding.utf8) else {
        fatalError("couldn't encode string as UTF-8")
    }
    
    // Convert JSON from NSData to AnyObject
    let jsonObject = try JSONSerialization.jsonObject(with: jsonData, options: [])
    
    // Try to convert AnyObject to array of strings
    if let stringArray = jsonObject as? [String] {
        print("Got array of strings: \(stringArray.joined(separator: ", "))")
    }
} catch {
    print("error reading JSON: \(error)")
}

do {
    // Convert object to JSON as NSData
    let jsonData = try JSONSerialization.data(withJSONObject: jsonObject, options: [])
    print("JSON data: \(jsonData)")

    // Convert NSData to String
    let jsonString = String(data: jsonData, encoding: .utf8)!
    print("JSON string: \(jsonString)")
} catch {
    print("error writing JSON: \(error)")
}

Nota: Lo siguiente está disponible actualmente solo en Swift 4.0 y versiones posteriores.

A partir de Swift 4.0, la biblioteca estándar Swift incluye los protocolos Encodable y Decodable para definir un enfoque estandarizado para la codificación de datos y la decodificación. La adopción de estos protocolos permitirá que las implementaciones de los protocolos de Encoder y Decoder tomen sus datos y los codifiquen o descodifiquen hacia y desde una representación externa como JSON. La conformidad con la Codable protocolo combina tanto la Encodable y Decodable protocolos. Este es ahora el medio recomendado para manejar JSON en su programa.

Codificar y decodificar automáticamente

La forma más fácil de hacer un tipo codificable es declarar sus propiedades como tipos que ya son Codable . Estos tipos incluyen tipos de biblioteca estándar como String , Int y Double ; y tipos de fundaciones, como Date , Data y URL . Si las propiedades de un tipo son codificables, el tipo en sí se ajustará automáticamente a Codable simplemente declarando la conformidad.

Considere el siguiente ejemplo, en el que la estructura del Book se ajusta a Codable .

struct Book: Codable {
    let title: String
    let authors: [String]
    let publicationDate: Date
}

Tenga en cuenta que las colecciones estándar como Array y Dictionary ajustan a Codable si contienen tipos codificables.

Al adoptar Codable , la estructura del Book ahora se puede codificar y descodificar desde JSON utilizando las clases JSONEncoder y JSONDecoder Apple Foundation, aunque Book no contiene ningún código para manejar específicamente JSON. Los codificadores y decodificadores personalizados también pueden escribirse, de conformidad con los protocolos Encoder y Decoder , respectivamente.

Codificar a datos JSON

// Create an instance of Book called book
let encoder = JSONEncoder()
let data = try! encoder.encode(book) // Do not use try! in production code
print(data)

Configure encoder.outputFormatting = .prettyPrinted para una lectura más fácil. ## Decodificar a partir de datos JSON

Decodificar a partir de datos JSON

// Retrieve JSON string from some source
let jsonData = jsonString.data(encoding: .utf8)!
let decoder = JSONDecoder()
let book = try! decoder.decode(Book.self, for: jsonData) // Do not use try! in production code
print(book)

En el ejemplo anterior, Book.self informa al decodificador del tipo al que se debe decodificar el JSON.

Codificación o decodificación exclusiva

A veces es posible que no necesite que los datos sean codificables y decodificables, como cuando solo necesita leer datos JSON de una API, o si su programa solo envía datos JSON a una API.

Si solo desea escribir datos JSON, ajuste su tipo a Encodable .

struct Book: Encodable {
    let title: String
    let authors: [String]
    let publicationDate: Date
}

Si solo desea leer datos JSON, ajuste su tipo a Decodable .

struct Book: Decodable {
    let title: String
    let authors: [String]
    let publicationDate: Date
}

Usando Nombres Clave Personalizados

Las API utilizan con frecuencia convenciones de nomenclatura distintas de la caja de camello estándar de Swift, como la caja de serpiente. Esto puede convertirse en un problema cuando se trata de decodificar JSON, ya que, de forma predeterminada, las claves JSON deben alinearse exactamente con los nombres de propiedad de su tipo. Para manejar estos escenarios, puede crear claves personalizadas para su tipo usando el protocolo CodingKey .

struct Book: Codable {
    // ...
    enum CodingKeys: String, CodingKey { 
        case title
        case authors
        case publicationDate = "publication_date"
    }
}

CodingKeys se generan automáticamente para los tipos que adoptan el protocolo Codable , pero al crear nuestra propia implementación en el ejemplo anterior, permitimos que nuestro decodificador Codable coincidir la fecha de publicationDate caso de camello local con la fecha de publication_date caso de serpiente como lo entrega la API.