Converter Dicionário para JSON no Swift

188

Eu criei o próximo dicionário:

var postJSON = [ids[0]:answersArray[0], ids[1]:answersArray[1], ids[2]:answersArray[2]] as Dictionary

e eu recebo:

[2: B, 1: A, 3: C]

Então, como posso convertê-lo para JSON?

Orkhan Alizade
fonte
1
NSJSONSerialization
Matthias Bauch

Respostas:

240

Swift 3.0

Com o Swift 3, o nome NSJSONSerializatione seus métodos foram alterados, de acordo com as Diretrizes de design da API do 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
    }
}

Eric Aya
fonte
Eu recebo o próximo [2: A, 1: A, 3: A]. Mas e os colchetes?
Orkhan Alizade
1
Eu não entendo sua pergunta. Que colchetes? Você perguntou sobre a codificação de um dicionário em JSON, e essa é a minha resposta.
Eric Aya
1
JSON colchetes, como{"result":[{"body":"Question 3"}] }
Orkhan Alizade 14/04
2
@OrkhanAlizade A chamada acima, para dataWithJSONObject se produzir as "chaves" (isto é, as cintas) como parte do resultante NSDataobjecto.
Rob
obrigado. nota lateral - considere usar d0 para abreviar (dic).
Johndpope 21/07
166

Você está fazendo uma suposição errada. Só porque o depurador / Playground mostra seu dicionário entre colchetes (que é como o Cocoa exibe dicionários) não significa que é dessa maneira que a saída JSON é formatada.

Aqui está um código de exemplo que converterá um dicionário de strings para JSON:

Versão 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 exibir o texto acima em formato "bastante impresso", altere a linha de opções para:

    options: [.prettyPrinted]

Ou na sintaxe do 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!)")

A saída disso é

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

Ou no formato bonito:

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

O dicionário é colocado entre chaves na saída JSON, exatamente como você esperaria.

EDITAR:

Na sintaxe Swift 3/4, o código acima se parece com o seguinte:

  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)")
    }
  }
Duncan C
fonte
Uma string Swift regular também funciona na declaração JSONText.
Fred Faust
@ thefredelement, como você converte o NSData diretamente em uma string Swift? A conversão de dados em string é uma função do NSString.
Duncan C
Eu estava implementando esse método e usei o init de dados / codificação em uma string Swift, não tenho certeza se isso estava disponível no Swift 1.x.
Fred Faust
Salvou o meu dia. Obrigado.
Shobhit C
resposta deve ser selecionada (y)
iBug 12/02/19
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)
    }
}

Observe que chaves e valores devem ser implementados Codable. Strings, Ints e Doubles (e mais) já são Codable. Consulte Tipos personalizados de codificação e decodificação .

Ryan H
fonte
26

Minha resposta para sua pergunta está abaixo

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)

A resposta é

{
  "0" : "ArrayObjectOne",
  "1" : "ArrayObjecttwo",
  "2" : "ArrayObjectThree"
}
user3182143
fonte
24

DictionaryExtensão 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)
    }
}
thexande
fonte
Essa é uma maneira boa e reutilizável de resolver o problema, mas uma pequena explicação ajudaria os novatos a entendê-lo melhor.
Nilobarp 19/03/19
Isso pode ser aplicado se as chaves do dicionário contiverem uma matriz de objetos personalizados?
Raju yourPepe
2
Não é uma boa ideia usar encoding: .asciiem extensão pública. .utf8será muito mais seguro!
ArtFeel 10/09/19
isso imprime com caracteres de escape existe algum lugar para impedir isso?
MikeG 19/02
23

Às vezes, é necessário imprimir a resposta do servidor para fins de depuração. Aqui está uma função que eu 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)
    }

}

Exemplo 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"
}
Andrey Gordeev
fonte
10

Swift 3 :

let jsonData = try? JSONSerialization.data(withJSONObject: dict, options: [])
let jsonString = String(data: jsonData!, encoding: .utf8)!
print(jsonString)
Bilal
fonte
Isso travará se qualquer parte for nula, uma prática muito ruim para forçar a desembrulhar os resultados. // De qualquer forma, já existem as mesmas informações (sem a falha) em outras respostas, evite postar conteúdo duplicado. Obrigado.
Eric Aya
5

A resposta para sua pergunta está abaixo:

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)
        }
Dheeraj D
fonte
2

Aqui está uma extensão fácil para fazer isso:

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
    }

}
StevenOjo
fonte
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
}
Swati Desai
fonte
1
Vários erros aqui. Por que usar o NSDictionary da Foundation em vez do Swift's Dictionary ?! Também por que retornar um novo dicionário com uma String como valor, em vez de retornar os dados JSON reais? Isso não faz sentido. Além disso, o opcional implicitamente desembrulhado retornado como opcional não é realmente uma boa idéia.
Eric Aya