Convertir diccionario a JSON en Swift


Respuestas:


240

Swift 3.0

Con Swift 3, el nombre NSJSONSerializationy sus métodos han cambiado, de acuerdo con las Pautas de diseño de API de Swift .

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


Me sale el siguiente [2: A, 1: A, 3: A]. ¿Pero qué hay de las llaves?
Orkhan Alizade

1
No entiendo tu pregunta. ¿Qué corchetes? Preguntaste sobre codificar un diccionario en JSON, y esa es mi respuesta.
Eric Aya

1
JSON llaves, como{"result":[{"body":"Question 3"}] }
Orkhan Alizade

2
@OrkhanAlizade La llamada anterior para dataWithJSONObject que producir las "llaves" (es decir, los frenos) como parte de la resultante NSDataobjeto.
Rob

Gracias. nota al margen: considere usar d0 en su lugar para abreviar (diccionario).
johndpope

166

Estás haciendo una suposición equivocada. El hecho de que el depurador / Playground muestre su diccionario entre corchetes (así es como Cocoa muestra los diccionarios) no significa que esa sea la forma en que se formatea la salida JSON.

Aquí hay un código de ejemplo que convertirá un diccionario de cadenas a JSON:

Versión Swift 3:

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

Para mostrar lo anterior en formato "bastante impreso", debe cambiar la línea de opciones a:

    options: [.prettyPrinted]

O en la sintaxis de Swift 2:

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

La salida de eso es

"JSON string = {"anotherKey":"anotherValue","aKey":"aValue"}"

O en formato bonito:

{
  "anotherKey" : "anotherValue",
  "aKey" : "aValue"
}

El diccionario está encerrado entre llaves en la salida JSON, tal como cabría esperar.

EDITAR:

En la sintaxis Swift 3/4, el código anterior se ve así:

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

Una cadena Swift normal también funciona en la declaración JSONText.
Fred Faust el

@thefredelement, ¿cómo se convierte NSData directamente en una cadena Swift? La conversión de datos a cadenas es una función de NSString.
Duncan C

Estaba implementando este método y utilicé el inicio de datos / codificación en una cadena Swift, no estoy seguro de si estaba disponible en Swift 1.x.
Fred Faust

Me salvó el día Gracias.
Shobhit C

debe seleccionarse la respuesta (y)
iBug

50

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

Tenga en cuenta que las claves y los valores deben implementarse Codable. Cadenas, Ints y Dobles (y más) ya están Codable. Consulte Codificación y decodificación de tipos personalizados .


26

Mi respuesta a tu pregunta está abajo

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: NSUTF8StringEncoding)! as String

print(jsonString)

La respuesta es

{
  "0" : "ArrayObjectOne",
  "1" : "ArrayObjecttwo",
  "2" : "ArrayObjectThree"
}

24

A veces es necesario imprimir la respuesta del servidor con fines de depuración. Aquí hay una función que uso:

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

}

Ejemplo de uso:

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

24

DictionaryExtensión Swift 4 .

extension Dictionary {
    var jsonStringRepresentation: String? {
        guard let theJSONData = try? JSONSerialization.data(withJSONObject: self,
                                                            options: [.prettyPrinted]) else {
            return nil
        }

        return String(data: theJSONData, encoding: .ascii)
    }
}

Esta es una forma buena y reutilizable de resolver el problema, pero una pequeña explicación ayudaría a los recién llegados a comprenderlo mejor.
nilobarp

¿Podría aplicarse esto si las claves del diccionario contienen una matriz de objetos personalizados?
Raju yourPepe

2
No es buena idea usarlo encoding: .asciien extensión pública. .utf8será mucho más seguro!
ArtFeel

esto imprime con caracteres de escape ¿hay algún lugar para evitar eso?
MikeG

10

Swift 3 :

let jsonData = try? JSONSerialization.data(withJSONObject: dict, options: [])
let jsonString = String(data: jsonData!, encoding: .utf8)!
print(jsonString)

Esto se bloqueará si alguna parte es nula, muy mala práctica para forzar el desenvolvimiento de los resultados. // De todos modos, ya hay la misma información (sin el bloqueo) en otras respuestas, evite publicar contenido duplicado. Gracias.
Eric Aya

5

La respuesta a su pregunta está a continuación:

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

2

Aquí hay una extensión fácil para hacer esto:

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
    }

}

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

1
Varios errores aquí. ¿Por qué usar NSDictionary de Foundation en lugar de Swift's Dictionary? Además, ¿por qué devolver un nuevo diccionario con una Cadena como valor, en lugar de devolver los datos JSON reales? Esto no tiene sentido. Además, el opcional envuelto implícitamente devuelto como opcional realmente no es una buena idea en absoluto.
Eric Aya
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.