【问题标题】:How do I deserialize a JSON string into an NSDictionary? (For iOS 5+)如何将 JSON 字符串反序列化为 NSDictionary? (适用于 iOS 5+)
【发布时间】:2012-01-26 05:54:32
【问题描述】:

在我的 iOS 5 应用程序中,我有一个包含 JSON 字符串的 NSString。我想将该 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]: unrecognized selector sent to instance 0x1372c”
  • 参见my answer,它展示了将 JSON 字符串反序列化为 Swift 3 和 Swift 4 字典的两种不同方法。

标签: ios json ios5 nsstring nsdictionary


【解决方案1】:

看起来您正在传递一个 NSString 参数,而您应该传递一个 NSData 参数:

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

【讨论】:

  • @Abizem,我可以在这里使用什么错误? (op没有提到)
  • 谢谢...这个帮助!和 +1
  • 谢谢,它成功了。但是,在 XCode 5 中使用 nil 作为错误而不是 &e
  • 我喜欢 Objective C。将你的字符串编码为原始字节,然后将它们解码回 NSStrings 和 NSNumbers。这很明显,不是吗?
  • @Abizern 通常从应用程序外部的某个地方接收 JSON 作为字符串
【解决方案2】:
NSData *data = [strChangetoJSON dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data
                                                             options:kNilOptions
                                                               error:&error];

例如,您在NSString strChangetoJSON 中有一个带有特殊字符的NSString。 然后你可以使用上面的代码将该字符串转换为 JSON 响应。

【讨论】:

    【解决方案3】:

    我从@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; Minor nitpick,但我认为值得一提。
    • @Mike,我认为无论值如何都可以检查“错误”?因为,如果出现错误,我们会立即返回 nil
    • 根据苹果的文档“在处理通过引用传递的错误时,重要的是要测试方法的返回值,看看是否发生了错误,如上所示。不要只测试看是否错误指针被设置为指向错误。” developer.apple.com/library/ios/documentation/Cocoa/Conceptual/…我相信这是因为可能存在没有发生错误并且方法返回值的情况,但是错误指针指向的内存被写入,所以你错误地认为存在错误。
    • 我在之前的一个问题中受过教育:“变量未初始化。这意味着该地址的值未定义,因此更改该值没有任何意义......因为有不保证如果没有发生错误,该方法不会将垃圾写入地址,Apple 的文档说测试错误变量的值是不安全的。” stackoverflow.com/questions/25558442/…
    • @Mike,太好了,很高兴知道!感谢您的参考。我会尽快更新。
    【解决方案4】:

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

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

    返回一个包含使用给定编码编码的字符串表示形式的数据。

    在 Swift 4 中,Stringdata(using:allowLossyConversion:) 可以与 JSONDecoderdecode(_:from:) 结合使用,以便将 JSON 字符串反序列化为字典。

    此外,对于 Swift 3 和 Swift 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 表示中解码给定类型的顶级值。

    下面的 Playground 代码显示了如何使用 data(using:allowLossyConversion:)decode(_:from:) 从 JSON 格式的 String 中获取 Dictionary

    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 代码显示了如何使用 data(using:allowLossyConversion:)json​Object(with:​options:​) 从 JSON 格式的 String 中获取 Dictionary

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

    【讨论】:

      【解决方案5】:

      在 swift 2.2 中使用 Abizern 代码

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-08-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多