Konwertuj słownik na JSON w Swift


Odpowiedzi:


240

Swift 3.0

W Swift 3 nazwa NSJSONSerializationi jej metody uległy zmianie, zgodnie z wytycznymi projektowymi API 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)
}

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


Dostaję następny [2: A, 1: A, 3: A]. Ale co z nawiasami klamrowymi?
Orkhan Alizade

1
Nie rozumiem twojego pytania. Jakie nawiasy klamrowe? Zapytałeś o kodowanie słownika w JSON, i to moja odpowiedź.
Eric Aya

1
Nawiasy klamrowe JSON, takie jak{"result":[{"body":"Question 3"}] }
Orkhan Alizade

2
@OrkhanAlizade Powyższy wywołanie dataWithJSONObject będzie produkować „nawiasów klamrowych” (czyli wzmocnienia) jako część powstałego NSDataobiektu.
Rob

dzięki. uwaga dodatkowa - rozważ użycie d0 zamiast skrótu (dic).
johndpope

166

Dokonujesz błędnego założenia. Tylko dlatego, że debugger / Plac zabaw pokazuje Twój słownik w nawiasach kwadratowych (tak jak Cocoa wyświetla słowniki), co nie znaczy, że tak jest sformatowane wyjście JSON.

Oto przykładowy kod, który przekonwertuje słownik ciągów na JSON:

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

Aby wyświetlić powyższe w formacie „ładnie wydrukowanym”, zmień wiersz opcji na:

    options: [.prettyPrinted]

Lub w składni 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!)")

Wynikiem tego jest

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

Lub w ładnym formacie:

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

Słownik jest zamknięty w nawiasach klamrowych na wyjściu JSON, tak jak można się spodziewać.

EDYTOWAĆ:

W składni Swift 3/4 powyższy kod wygląda następująco:

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

Zwykły ciąg Swift działa również w deklaracji JSONText.
Fred Faust

@thefredelement, jak przekonwertować NSData bezpośrednio na ciąg Swift? Konwersja danych na ciąg jest funkcją NSString.
Duncan C

Wdrażałem tę metodę i użyłem init danych / kodowania w łańcuchu Swift, nie jestem pewien, czy był on dostępny w Swift 1.x.
Fred Faust

Uratowałem mój dzień. Dzięki.
Shobhit C

należy wybrać odpowiedź (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)
    }
}

Pamiętaj, że klucze i wartości muszą zostać zaimplementowane Codable. Strings, Ints i Doubles (i więcej) są już Codable. Zobacz Kodowanie i dekodowanie typów niestandardowych .


26

Moja odpowiedź na twoje pytanie znajduje się poniżej

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)

Odpowiedź to

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

24

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

Jest to dobry i wielokrotnego użytku sposób rozwiązania problemu, ale małe wyjaśnienie pomogłoby początkującym lepiej go zrozumieć.
nilobarp

Czy można to zastosować, jeśli klucze słownika zawierają tablicę niestandardowych obiektów?
Raju yourPepe

2
Nie jest dobrym pomysłem korzystanie encoding: .asciiz rozszerzenia publicznego. .utf8będzie znacznie bezpieczniejszy!
ArtFeel,

to odciski ze znakami ucieczki czy istnieje gdziekolwiek, aby temu zapobiec?
MikeG

23

Czasami konieczne jest wydrukowanie odpowiedzi serwera do celów debugowania. Oto funkcja, której używam:

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

}

Przykład zastosowania:

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

10

Swift 3 :

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

Spowoduje to awarię, jeśli jakakolwiek część jest zerowa, bardzo zła praktyka wymuszania rozpakowywania wyników. // W każdym razie już te same informacje (bez awarii) w innych odpowiedziach, unikaj publikowania zduplikowanych treści. Dzięki.
Eric Aya,

5

Odpowiedź na twoje pytanie znajduje się poniżej:

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

Oto łatwe rozszerzenie, aby to zrobić:

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
Kilka błędów tutaj. Dlaczego warto używać NSDictionary Foundation zamiast Swift's Dictionary ?! Także po co zwracać nowy słownik z wartością String jako wartość, zamiast zwracać rzeczywiste dane JSON? To nie ma sensu. Również niejawnie rozpakowana opcja opcjonalna zwrócona jako opcja nie jest wcale dobrym pomysłem.
Eric Aya,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.