WebAPIやJSONRPCを利用する際、よくフォーマットとして利用されるのがJSONです。Foundation FrameworkにもJSONのシリアライズやデシリアライズを行うクラスが含まれています。この章ではそのクラスの利用法を説明します。
クラスリファレンスはこちら https://developer.apple.com/reference/foundation/jsonserialization
JSONのシリアライズ、デシリアライズを行うクラスはJSONSerializationです。このクラスを用いてData <--> JSONオブジェクトを変換するには以下の制約があります。
- トップレベルオブジェクトはNSArrayかNSDictionaryである
- 全てのオブジェクトは, NSString, NSNumber, NSArray, NSDictionary, NSNull いずれかのインスタンスである
- 全ての辞書のキーはNSString
- 数値はNaNや無限でない
変換することができるかを調べるメソッドとしてclass func isValidJSONObject(_ obj: Any) -> Bool
があります。
URLSessionのレスポンスなどの結果をJSONオブジェクトに変換します。変換には
class func jsonObject(with data: Data, options opt: JSONSerialization.ReadingOptions = []) throws -> Any
を用います。引数としてNSDataとオプションを渡します。デシリアライズに失敗した時は例外が発生しcatchしたerrorにその理由が含まれます。またオプションには以下の物があります。
JSONSerialization.ReadingOptions | 説明 |
---|---|
mutableContainers | 利用するオブジェクトをNSMutableArray, NSMutabileDictionaryで変換します |
mutableLeaves | オブジェクトのキーとしてNSMutableStringを用います |
allowFragments | JSONのトップレベルオブジェクトとしてDictionary, Array以外を指定できます。( "hoge" のような文字列のみでも変換できます) |
実行例
以下の文字列についてパースを行います。
let jsonString = "{" +
" \"employees\" : [" +
" { \"lastName\" : \"Doe\", \"firstName\" : \"John\" }," +
" { \"lastName\" : \"Smith\", \"firstName\" : \"Anna\" }," +
" { \"lastName\" : \"Jones\", \"firstName\" : \"Peter\" }" +
" ]" +
"}"
変換コード
let data = jsonString.data(using: String.Encoding.utf8)!
do {
let object = try JSONSerialization.jsonObject(with: data, options: .mutableContainers)
print(object)
} catch let e {
print(e)
}
出力結果
{
employees = (
{
firstName = John;
lastName = Doe;
},
{
firstName = Anna;
lastName = Smith;
},
{
firstName = Peter;
lastName = Jones;
}
);
}
JSONオブジェクトからDataへの変換には
class func data(withJSONObject obj: Any, options opt: JSONSerialization.WritingOptions = []) throws -> Data
を用います。基本的な使い方は上記の逆となります。JSONのトップレベルオブジェクトを引数として渡します。同時にオプションとエラーへのポインタを渡します。変換に成功したらUTF-8でエンコードされた文字列のDataが返されます。エラーがあったときはerrorにその内容が含まれます。
上記データを逆にDataに変換したサンプルは以下のようになります。
変換コード
do {
let data = try JSONSerialization.data(withJSONObject: object, options: [])
let jsonString = String(data: data, encoding: String.Encoding.utf8)
print(jsonString!)
} catch let e {
print(e)
}
出力結果
{"employees":[{"firstName":"John","lastName":"Doe"},{"firstName":"Anna","lastName":"Smith"},{"firstName":"Peter","lastName":"Jones"}]}
またオプションとしてNSJSONWritingPrettyPrintedを渡すと改行やインデントを含めた文字列のDataがレスポンスになります。
{
"employees" : [
{
"firstName" : "John",
"lastName" : "Doe"
},
{
"firstName" : "Anna",
"lastName" : "Smith"
},
{
"firstName" : "Peter",
"lastName" : "Jones"
}
]
}