Wie deserialisiere ich eine JSON-Zeichenfolge in ein NSDictionary? (Für iOS 5+)

154

In meiner iOS 5-App habe ich eine NSString, die eine JSON-Zeichenfolge enthält. Ich möchte diese JSON-Zeichenfolgendarstellung in ein natives NSDictionaryObjekt deserialisieren .

 "{\"password\" : \"1234\",  \"user\" : \"andreas\"}"

Ich habe folgenden Ansatz versucht:

NSDictionary *json = [NSJSONSerialization JSONObjectWithData:@"{\"2\":\"3\"}"
                                options:NSJSONReadingMutableContainers
                                  error:&e];  

Aber es wird ein Laufzeitfehler ausgegeben. Was mache ich falsch?

-[__NSCFConstantString bytes]: unrecognized selector sent to instance 0x1372c 
*** Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: '-[__NSCFConstantString bytes]: unrecognized selector sent to instance 0x1372c'
Andreas
quelle
Das war mein Ansatz: NSDictionary * JSON = [NSJSONSerialization JSONObjectWithData: @ "{" 2 ":" 3 "}" Optionen: NSJSONReadingMutableContainers Fehler: & e]; Ich erhalte: 2011-12-22 17: 18: 59.300 Pi9000 [938: 13803] - [__ NSCFConstantString-Bytes]: Nicht erkannter Selektor an Instanz 0x1372c gesendet 2011-12-22 17: 18: 59.302 Pi9000 [938: 13803] *** Beenden der App aufgrund der nicht erfassten Ausnahme 'NSInvalidArgumentException', Grund: '- [__ NSCFConstantString-Bytes]: Nicht erkannter Selektor an Instanz 0x1372c gesendet'
Andreas
Siehe meine Antwort , die zwei verschiedene Möglichkeiten zeigt, eine JSON-Zeichenfolge in ein Wörterbuch für Swift 3 und Swift 4 zu deserialisieren.
Imanou Petit

Antworten:

335

Es sieht so aus, als würden Sie einen NSStringParameter übergeben, an den Sie einen NSDataParameter übergeben sollten:

NSError *jsonError;
NSData *objectData = [@"{\"2\":\"3\"}" dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:objectData
                                      options:NSJSONReadingMutableContainers 
                                        error:&jsonError];
Abizern
quelle
@Abizem, welchen Fehler könnte ich hier verwenden? (op erwähnt es nicht)
Danke ... dieser hat geholfen! und +1
Jayprakash Dubey
Danke, es hat funktioniert. Verwendung nilals Fehler anstelle von &eXCode 5
Michael Ho Chum
3
Ich mag Ziel C. Codieren Sie Ihre Zeichenfolge in Rohbytes und dekodieren Sie sie dann zurück in NSStrings und NSNumbers. Das ist offensichtlich, nicht wahr?
Vahotm
1
@Abizern Es ist üblich, JSON als Zeichenfolge von außerhalb Ihrer Anwendung zu erhalten
Chicowitz
37
NSData *data = [strChangetoJSON dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data
                                                             options:kNilOptions
                                                               error:&error];

Zum Beispiel haben Sie ein NSStringmit Sonderzeichen in NSStringstrChangetoJSON. Anschließend können Sie diese Zeichenfolge mit dem obigen Code in eine JSON-Antwort konvertieren.

Wüstenrose
quelle
6

Ich habe eine Kategorie aus @Abizern Antwort gemacht

@implementation NSString (Extensions)
- (NSDictionary *) json_StringToDictionary {
    NSError *error;
    NSData *objectData = [self dataUsingEncoding:NSUTF8StringEncoding];
    NSDictionary *json = [NSJSONSerialization JSONObjectWithData:objectData options:NSJSONReadingMutableContainers error:&error];
    return (!json ? nil : json);
}
@end

Verwenden Sie es so,

NSString *jsonString = @"{\"2\":\"3\"}";
NSLog(@"%@",[jsonString json_StringToDictionary]);
Hemang
quelle
Nach meinem Verständnis ist es empfehlenswert, errorin diesen Fällen nicht zu testen , sondern vor der Rückkehr zu testen, ob der Rückgabewert Null ist oder nicht. dh return json ?: nil; Minor Nitpick, aber erwähnenswert, denke ich.
Mike
@ Mike, ich denke, es ist in Ordnung, unabhängig vom Wert auf "Fehler" zu prüfen? Denn wenn es einen Fehler gibt, kehren wir nilsofort zurück.
Hemang
In den Apple-Dokumenten heißt es: "Wenn Sie mit Fehlern arbeiten, die als Referenz übergeben wurden, ist es wichtig, den Rückgabewert der Methode zu testen, um festzustellen, ob ein Fehler aufgetreten ist, wie oben gezeigt. Testen Sie nicht nur, ob der Fehlerzeiger so eingestellt ist, dass er auf zeigt." ein Fehler." developer.apple.com/library/ios/documentation/Cocoa/Conceptual/… Ich glaube, das liegt daran, dass es Fälle geben kann, in denen kein Fehler auftritt und die Methode einen Wert zurückgibt, aber der Speicher, auf den der Fehlerzeiger zeigt geschrieben an, so dass Sie fälschlicherweise glauben, dass ein Fehler vorliegt.
Mike
Ich wurde in einer meiner vorherigen Fragen geschult: "Die Variable ist nicht initialisiert. Das bedeutet, dass der Wert an dieser Adresse nicht definiert ist. Das Ändern des Werts bedeutet also nichts ... Da es keine Garantie gibt, dass die Methode nicht schreibt." Wenn ein Fehler nicht auftritt, wird in den Apple-Dokumenten angegeben, dass es unsicher ist, den Wert der Fehlervariablen zu testen. " stackoverflow.com/questions/25558442/…
Mike
1
@ Mike, oh toll, gut zu wissen! Danke für die Referenzen. Ich werde dies bald aktualisieren.
Hemang
5

Mit Swift 3 und Swift 4 Stringwird eine Methode aufgerufen data(using:allowLossyConversion:). data(using:allowLossyConversion:)hat die folgende Erklärung:

func data(using encoding: String.Encoding, allowLossyConversion: Bool = default) -> Data?

Gibt Daten zurück, die eine Darstellung des mit einer bestimmten Codierung codierten Strings enthalten.

Mit Swift 4 kann String's data(using:allowLossyConversion:)in Verbindung mit JSONDecoder' s verwendet decode(_:from:)werden, um eine JSON-Zeichenfolge in ein Wörterbuch zu deserialisieren.

Darüber hinaus können mit Swift 3 und Swift 4 String's data(using:allowLossyConversion:)auch in Verbindung mit JSONSerialization' s verwendet json​Object(with:​options:​)werden, um eine JSON-Zeichenfolge in ein Wörterbuch zu deserialisieren.


# 1. Swift 4-Lösung

Mit Swift 4 JSONDecoderwird eine Methode aufgerufen decode(_:from:). decode(_:from:)hat die folgende Erklärung:

func decode<T>(_ type: T.Type, from data: Data) throws -> T where T : Decodable

Dekodiert einen Wert der obersten Ebene des angegebenen Typs aus der angegebenen JSON-Darstellung.

Der folgende Spielplatzcode zeigt, wie data(using:allowLossyConversion:)und decode(_:from:)um einen Dictionaryvon einem JSON formatierten zu erhalten String:

let jsonString = """
{"password" : "1234",  "user" : "andreas"}
"""

if let data = jsonString.data(using: String.Encoding.utf8) {
    do {
        let decoder = JSONDecoder()
        let jsonDictionary = try decoder.decode(Dictionary<String, String>.self, from: data)
        print(jsonDictionary) // prints: ["user": "andreas", "password": "1234"]
    } catch {
        // Handle error
        print(error)
    }
}

# 2. Swift 3 und Swift 4 Lösung

Mit Swift 3 und Swift 4 JSONSerializationwird eine Methode aufgerufen json​Object(with:​options:​). json​Object(with:​options:​)hat die folgende Erklärung:

class func jsonObject(with data: Data, options opt: JSONSerialization.ReadingOptions = []) throws -> Any

Gibt ein Foundation-Objekt aus angegebenen JSON-Daten zurück.

Der folgende Spielplatzcode zeigt, wie data(using:allowLossyConversion:)und json​Object(with:​options:​)um einen Dictionaryvon einem JSON formatierten zu erhalten String:

import Foundation

let jsonString = "{\"password\" : \"1234\",  \"user\" : \"andreas\"}"

if let data = jsonString.data(using: String.Encoding.utf8) {
    do {
        let jsonDictionary = try JSONSerialization.jsonObject(with: data, options: []) as? [String : String]
        print(String(describing: jsonDictionary)) // prints: Optional(["user": "andreas", "password": "1234"])
    } catch {
        // Handle error
        print(error)
    }
}
Imanou Petit
quelle
3

Verwenden von Abizern- Code für Swift 2.2

let objectData = responseString!.dataUsingEncoding(NSUTF8StringEncoding)
let json = try NSJSONSerialization.JSONObjectWithData(objectData!, options: NSJSONReadingOptions.MutableContainers)
IOS Singh
quelle