JSON文字列をNSDictionaryに逆シリアル化するにはどうすればよいですか?(iOS 5以降の場合)


154

私のiOS 5アプリにNSStringは、JSON文字列を含むがあります。そのJSON文字列表現をネイティブNSDictionaryオブジェクトに逆シリアル化したいと思います。

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

私は次のアプローチを試しました:

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

ただし、ランタイムエラーがスローされます。何が悪いのですか?

-[__NSCFConstantString bytes]: unrecognized selector sent to instance 0x1372c 
*** Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: '-[__NSCFConstantString bytes]: unrecognized selector sent to instance 0x1372c'

それが私のアプローチでした:NSDictionary * JSON = [NSJSONSerialization JSONObjectWithData:@ "{\" 2 \ ":\" 3 \ "}"オプション:NSJSONReadingMutableContainersエラー:&e]; 取得:2011-12-22 17:18:59.300 Pi9000 [938:13803]-[__ NSCFConstantString bytes]:認識されないセレクターがインスタンス0x1372cに送信されました2011-12-22 17:18:59.302 Pi9000 [938:13803] ***キャッチされない例外「NSInvalidArgumentException」によるアプリの終了、理由:「-[__ NSCFConstantString bytes]:認識されないセレクターがインスタンス0x1372cに送信されました」
Andreas

参照してください私の答えを示してスウィフト3とスウィフト4の辞書にJSON文字列をデシリアライズするには、2つの異なった方法ということ
Imanouプチ

回答:


335

NSStringパラメータを渡す必要がある場所にパラメータを渡しているようですNSData

NSError *jsonError;
NSData *objectData = [@"{\"2\":\"3\"}" dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:objectData
                                      options:NSJSONReadingMutableContainers 
                                        error:&jsonError];

@Abizem、ここでどのエラーを使用できますか?(opはそれについて言及していません)

ありがとう...これは役に立ちました!および+1
Jayprakash Dubey 2014

ありがとう、うまくいきました。ただし、XCode 5 nilではなくエラーとして使用&e
Michael Ho Chum

3
私はObjective Cが好きです。文字列を生のバイトにエンコードしてから、デコードしてNSStringsとNSNumbersに戻します。これは明白ですよね?
vahotm 2015年

1
@Abizernは、アプリケーションの外部のどこかからJSONを文字列として受信するのが一般的です
Chicowitz

37
NSData *data = [strChangetoJSON dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data
                                                             options:kNilOptions
                                                               error:&error];

たとえばNSStringNSStringstrChangetoJSONに特殊文字付きのがあるとします。次に、上記のコードを使用してその文字列をJSON応答に変換できます。


6

@Abizernの回答からカテゴリを作成しました

@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

このように使って、

NSString *jsonString = @"{\"2\":\"3\"}";
NSLog(@"%@",[jsonString json_StringToDictionary]);

errorこれらのケースではテストせず、返す前に戻り値がnilかどうかをテストすることがベストプラクティスであることは私の理解です。つまり、 return json ?: nil; マイナーニッピックですが、言及する価値があると思います。
Mike

@マイク、私は値に関係なく「エラー」をチェックしても大丈夫だと思いますか?なぜなら、エラーが発生した場合は、nilすぐに戻るからです。
Hemang

Appleのドキュメントによると、「参照渡しのエラーを処理する場合、メソッドの戻り値をテストして、上記のようにエラーが発生したかどうかを確認することが重要です。エラーポインタがエラー。" developer.apple.com/library/ios/documentation/Cocoa/Conceptual/… これは、エラーが発生せず、メソッドが値を返す場合があるが、エラーポインターが指すメモリが書き込まれているため、エラーが存在すると誤って考えます。
Mike

私は私の以前の質問で学校に通っていました:「変数は初期化されていません。つまり、そのアドレスの値は定義されていないので、値を変更しても何の意味もありません...メソッドが書き込みを行わないという保証がないためです。エラーが発生しない場合にアドレスにゴミが出ると、Appleのドキュメントでは、エラー変数の値をテストするのは安全ではないとしています。」stackoverflow.com/questions/25558442/...
マイク・

1
@マイク、すごい、知っておきたい!参照をありがとう。これはまもなく更新されます。
Hemang

5

Swift 3とSwift 4では、Stringというメソッドがありdata(using:allowLossyConversion:)ます。data(using:allowLossyConversion:)次の宣言があります:

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

指定されたエンコーディングを使用してエンコードされた文字列の表現を含むデータを返します。

スイフト4で、String「Sはdata(using:allowLossyConversion:)と組み合わせて使用することができJSONDecoder、S」decode(_:from:)辞書にJSON文字列をデシリアライズするために。

また、スウィフト3及びスイフト4で、String'sはdata(using:allowLossyConversion:)またと共に使用することができるJSONSerializationjson​Object(with:​options:​)辞書にJSON文字列をデシリアライズするために。


#1。Swift 4ソリューション

Swift 4では、JSONDecoderというメソッドがありdecode(_:from:)ます。decode(_:from:)次の宣言があります:

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

指定されたJSON表現から指定されたタイプのトップレベルの値をデコードします。

以下のPlaygroundコードは、JSON形式からを使用data(using:allowLossyConversion:)decode(_:from:)て取得する方法を示しDictionaryています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およびSwift 4ソリューション

Swift 3とSwift 4では、JSONSerializationというメソッドがありjson​Object(with:​options:​)ます。json​Object(with:​options:​)次の宣言があります:

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

指定されたJSONデータからFoundationオブジェクトを返します。

以下のPlaygroundコードは、JSON形式からを使用data(using:allowLossyConversion:)json​Object(with:​options:​)て取得する方法を示しDictionaryています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)
    }
}

3

Swift 2.2のAbizernコードの使用

let objectData = responseString!.dataUsingEncoding(NSUTF8StringEncoding)
let json = try NSJSONSerialization.JSONObjectWithData(objectData!, options: NSJSONReadingOptions.MutableContainers)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.