如何将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字节]:无法识别的选择器发送到实例0x1372c 2011-12-22 17:18:59.302 Pi9000 [938:13803] ***由于未捕获的异常“ NSInvalidArgumentException”而终止应用程序,原因:“-[__ NSCFConstantString字节]:无法识别的选择器已发送至实例0x1372c”
Andreas

我的回答是显示了两种不同的方法来反序列化JSON字符串到字典斯威夫特3和斯威夫特4
Imanou佩蒂特

Answers:


335

看起来您要传递NSString参数,而应该传递NSData参数:

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

@Abizem,我在这里可以使用什么错误?(

谢谢...这个帮助!和+1
Jayprakash Dubey 2014年

谢谢,它有效。但是,使用nil错误代替&eXCode 5
Michael Ho Chum 2014年

3
我喜欢ObjectiveC。将您的字符串编码为原始字节,然后将其解码回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; 轻微的nitpick,但我想值得一提。
迈克

@Mike,我认为可以检查“错误”而不管其值如何?因为,如果发生错误,我们将立即返回nil
Hemang '16

根据Apple的文档,“当处理通过引用传递的错误时,测试该方法的返回值以查看是否发生了错误非常重要,如上所示。不要仅仅测试以查看错误指针是否设置为指向一个错误。” developer.apple.com/library/ios/documentation/Cocoa/Conceptual/… 我相信这是因为在某些情况下可能不会发生错误并且该方法返回一个值,但是错误指针指向的内存是写入,因此您错误地认为存在错误。
迈克,

我曾在我的一个先前的问题中受过教育:“变量未初始化。这意味着该地址的值未定义,因此更改值不会有任何意义...因为不能保证该方法不会写如果没有发生错误,则将其乱码到地址中​​,Apple的文档说,测试错误变量的值是不安全的。” stackoverflow.com/questions/25558442/…–
迈克

1
@Mike,哦,太好了,很高兴知道!感谢您的参考。我将尽快更新。
Hemang '16

5

对于Swift 3和Swift 4,String有一个称为的方法data(using:allowLossyConversion:)data(using:allowLossyConversion:)具有以下声明:

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

返回一个数据,该数据包含使用给定编码编码的String的表示形式。

在Swift 4中,可以将Strings data(using:allowLossyConversion:)JSONDecoders 结合使用decode(_:from:),以将JSON字符串反序列化为字典。

此外,夫特3和4斯威夫特,Stringdata(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表示形式解码给定类型的顶级值。

下面展示了如何使用该游乐场的代码data(using:allowLossyConversion:),并decode(_:from:)以获得Dictionary从JSON格式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对象。

下面展示了如何使用该游乐场的代码data(using:allowLossyConversion:),并json​Object(with:​options:​)以获得Dictionary从JSON格式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

使用Abizern代码进行Swift 2.2

let objectData = responseString!.dataUsingEncoding(NSUTF8StringEncoding)
let json = try NSJSONSerialization.JSONObjectWithData(objectData!, options: NSJSONReadingOptions.MutableContainers)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.