Làm cách nào để tôi giải tuần tự hóa chuỗi JSON thành NSDipedia? (Dành cho iOS 5+)


154

Trong ứng dụng iOS 5 của tôi, tôi có một NSStringchuỗi chứa chuỗi JSON. Tôi muốn giải tuần tự hóa biểu diễn chuỗi JSON đó thành một NSDictionaryđối tượng gốc .

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

Tôi đã thử cách tiếp cận sau:

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

Nhưng nó ném một lỗi thời gian chạy. Tôi đang làm gì sai?

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

Đó là cách tiếp cận của tôi: NSDadata * JSON = [NSJSONSerialization JSONObjectWithData: @ "{\" 2 \ ": \" 3 \ "}": NSJSONReadMutableContainers error: & e]; tôi nhận được: 2011-12-22 17: 18: 59.300 Pi9000 [938: 13804] - [__ NSCFConstantString byte]: bộ chọn không nhận dạng được gửi đến ví dụ 0x1372c 2011-12-22 17: 18: 59.302 Pi9000 [938: 13804 Chấm dứt ứng dụng do ngoại lệ chưa được phát hiện 'NSInvalidArgumentException', lý do: '- [__ NSCFConstantString byte]: bộ chọn không được nhận dạng được gửi đến ví dụ 0x1372c'
Andreas

Xem câu trả lời của tôi cho thấy hai cách khác nhau để giải tuần tự chuỗi JSON vào từ điển cho Swift 3 và Swift 4.
Imanou Petit

Câu trả lời:


335

Có vẻ như bạn đang truyền một NSStringtham số trong đó bạn sẽ truyền một NSDatatham số:

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

@Abizem, tôi có thể sử dụng lỗi gì ở đây? (op không đề cập đến nó)

Cảm ơn ... cái này đã giúp! và +1
Jayprakash Dubey

Cảm ơn, nó đã làm việc. Tuy nhiên, sử dụng nilnhư lỗi thay vì &etrong XCode 5
Michael Ho Chum

3
Tôi thích Objective C. Mã hóa chuỗi của bạn thành byte thô và sau đó giải mã chúng trở lại NSStrings và NSNumbers. Điều này là hiển nhiên, phải không?
vahotm

1
@Abizern thông thường để nhận JSON dưới dạng một chuỗi từ một nơi nào đó bên ngoài ứng dụng của bạn
Chicowitz

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

Ví dụ: bạn có một NSStringký tự đặc biệt trong NSStringstrChangetoJSON. Sau đó, bạn có thể chuyển đổi chuỗi đó thành phản hồi JSON bằng cách sử dụng mã ở trên.


6

Tôi đã tạo một danh mục từ câu trả lời @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

Sử dụng nó như thế này,

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

Theo hiểu biết của tôi, đó là cách tốt nhất để không kiểm tra errortrong những trường hợp này, mà thay vào đó để kiểm tra xem giá trị trả về có bằng không hay không trước khi trả về. tức là return json ?: nil; nitlog nhỏ, nhưng đáng nói, tôi nghĩ vậy.
Mike

@Mike, tôi nghĩ rằng ok để kiểm tra "lỗi" bất kể giá trị là gì? Bởi vì, nếu có lỗi thì chúng tôi sẽ quay lại nilngay.
Hemang

Theo tài liệu của Apple "Khi xử lý các lỗi được truyền bằng tham chiếu, điều quan trọng là phải kiểm tra giá trị trả về của phương thức để xem có xảy ra lỗi hay không, như được hiển thị ở trên. Đừng thử kiểm tra xem con trỏ lỗi có được đặt thành trỏ hay không một lỗi." developer.apple.com/l Library / ios / document / Cocoa / Conceptionual / Trực Tôi tin rằng điều này là do có thể xảy ra lỗi không xảy ra và phương thức trả về một giá trị, nhưng bộ nhớ mà con trỏ lỗi trỏ đến được viết cho, vì vậy bạn nghĩ sai một lỗi tồn tại.
Mike

Tôi đã được học trong một câu hỏi trước đây của tôi: "Biến không được khởi tạo. Điều đó có nghĩa là giá trị tại địa chỉ đó không được xác định, vì vậy thay đổi giá trị sẽ không có nghĩa gì cả ... Vì không có gì đảm bảo phương thức sẽ không viết rác vào địa chỉ nếu xảy ra lỗi, tài liệu của Apple nói rằng không an toàn để kiểm tra giá trị của biến lỗi. " stackoverflow.com/questions/25558442/ hy
Mike

1
@Mike, ồ tuyệt vời, thật tốt khi biết! Cảm ơn các tài liệu tham khảo. Tôi sẽ cập nhật điều này sớm.
Hemang

5

Với Swift 3 và Swift 4, Stringcó một phương thức gọi là data(using:allowLossyConversion:). data(using:allowLossyConversion:)có tuyên bố sau:

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

Trả về Dữ liệu chứa đại diện của Chuỗi được mã hóa bằng mã hóa đã cho.

Với Swift 4, String's data(using:allowLossyConversion:)có thể được sử dụng kết hợp với JSONDecoder' s decode(_:from:)để deserialize một chuỗi JSON thành một cuốn từ điển.

Hơn nữa, với Swift 3 và Swift 4, String's data(using:allowLossyConversion:)cũng có thể được sử dụng kết hợp với JSONSerialization' s json​Object(with:​options:​)để deserialize một chuỗi JSON thành một cuốn từ điển.


# 1. Giải pháp Swift 4

Với Swift 4, JSONDecodercó một phương thức gọi là decode(_:from:). decode(_:from:)có tuyên bố sau:

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

Giải mã một giá trị cấp cao nhất của loại đã cho từ biểu diễn JSON đã cho.

Mã Playground bên dưới hiển thị cách sử dụng data(using:allowLossyConversion:)decode(_:from:)để lấy Dictionarytừ JSON được định dạng 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. Giải pháp Swift 3 và Swift 4

Với Swift 3 và Swift 4, JSONSerializationcó một phương thức gọi là json​Object(with:​options:​). json​Object(with:​options:​)có tuyên bố sau:

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

Trả về một đối tượng Foundation từ dữ liệu JSON đã cho.

Mã Playground bên dưới hiển thị cách sử dụng data(using:allowLossyConversion:)json​Object(with:​options:​)để lấy Dictionarytừ JSON được định dạng 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

Sử dụng mã Abizern cho swift 2.2

let objectData = responseString!.dataUsingEncoding(NSUTF8StringEncoding)
let json = try NSJSONSerialization.JSONObjectWithData(objectData!, options: NSJSONReadingOptions.MutableContainers)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.