JSONSerialization — Foundationフレームワークの組み込みiOSクラスで、JSONをFoundationオブジェクトに変換したり、その逆を行うために設計されています。このAPIは、サードパーティライブラリなしでAppleプラットフォームでJSONを操作するための基本的な機構で、辞書、配列、プリミティブ型の解析をサポートします。Apple Developer, 2024によると、JSONSerializationは Data、ストリーム、および読み取りオプションをサポートし、柔軟なJSONデータ処理を可能にします。
メインポイント
JSONSerializationはFoundationフレームワークのクラスで、iOS、macOS、tvOS、watchOSで利用可能です。JSON DataをFoundationオブジェクト(NSDictionary、NSArray、NSString、NSNumber)に変換したり、その逆を行うメソッドを提供します。このクラスはiOS 5で登場し、Codable(Swift 4)が導入されるまで、AppleプラットフォームでJSONを操作する主な方法でした。古いクラスではありますが、JSONSerializationはレガシーObjective-Cプロジェクトや、固定されたモデルスキーマなしに動的なJSON処理が必要なシナリオで依然として重要です。
Codableの登場にもかかわらず、JSONSerializationはいくつかのシナリオで重要です。動的なJSON構造—応答形式が変わったり事前に不明な場合—には、キーで辞書にアクセスする必要があり、JSONSerializationを通じて行うのが簡単です。このクラスは、Codableが使用できないObjective-Cプロジェクトや、大きなJSONファイルを歩々に解析するためのストリーム処理でも使用されます。テストやモックアップでは、isValidJSONObjectやdata(withJSONObject:options:)を使用すると、サードパーティライブラリなしでJSONフィクスチャを高速に生成でき、開発とプロトタイピングを加速できます。
import Foundation
// JSONSerialization使用の基本構造
let jsonString = """
{
"id": 1,
"name": "John Doe",
"email": "john@example.com"
}
"""
guard let jsonData = jsonString.data(using: .utf8) else {
return
}
do {
let json = try JSONSerialization
.jsonObject(with: jsonData,
options: .mutableContainers)
print(json)
} catch {
print("JSON解析エラー: \(error)")
}
JSONSerializationは、JSONを操作するための4つの主なメソッドを提供します。主なメソッドはjsonObject(with:options:)で、DataをFoundationオブジェクトに変換します。data(withJSONObject:options:)メソッドは逆シリアライゼーションを行います。isValidJSONObject(_:)はオブジェクトがシリアライズ可能か確認します。writeJSONObject(_:to:options:error:)はJSONをストリームに直接書き込みます。InputStreamからJSONを読む場合は、Dataの代わりにストリームを受け取るjsonObject(with:options:)メソッドが便利で、ストリーミングデータを返すネットワークリクエストとの統合に役立ちます。
jsonObjectメソッドはDataを受け取り、Any(通常はNSDictionaryまたはNSArray)を返します。安全に使用するには、結果を条件付きキャストで期待される型に変換します。dataメソッドはFoundationオブジェクトを受け取り、JSON表現を持つDataを返します。.prettyPrintedオプションは可読性のためにインデント付きのフォーマットを追加します。
let jsonString = """
{
"products": [
{"id": 1, "name": "iPhone", "price": 999},
{"id": 2, "name": "iPad", "price": 799}
]
}
"""
let data = Data(jsonString.utf8)
if let json = try? JSONSerialization
.jsonObject(with: data) as? [String: Any],
let products = json["products"] as? [[String: Any]] {
for product in products {
if let name = product["name"] as? String {
print("製品: \(name)")
}
}
}
// 逆シリアライゼーション: オブジェクト -> JSON
let outputDict: [String: Any] = ["status": "ok", "count": 42]
if let outputData = try? JSONSerialization
.data(withJSONObject: outputDict,
options: .prettyPrinted) {
String(data: outputData, encoding: .utf8)
}
基本的な解析プリミティブ型の辞書は、JSONSerializationで最も一般的な操作です。URLSessionを通じてDataを受け取った後、開発者はjsonObjectを呼び出し、結果を期待される型にキャストします。オブジェクトの配列の場合は、[[String: Any]]へのキャストを使用し、各要素をループで処理します。このアプローチは柔軟ですが、型の手動管理が必要です。
実際のAPIは、配列、日付、オプショナルフィールドを含む複雑なネストされたJSONオブジェクトを返します。JSONSerializationはあらゆるネスト深さを正しく処理できますが、開発者は各レベルを必要な型に独自にキャストする必要があります。この作業を簡素化するために、Appleは型指定されたデータにはCodableを、動的な構造にのみJSONSerializationを使用することを推奨しています。
// API応答の解析
func parseUserResponse(data: Data) {
do {
guard let json = try JSONSerialization
.jsonObject(with: data) as? [String: Any]
else { return }
guard let userId = json["id"] as? Int,
let name = json["name"] as? String
else {
throw ParsingError.missingField
}
print("ユーザー: \(name) (ID: \(userId))")
} catch let error as ParsingError {
print("解析失敗: \(error)")
} catch {
print("予期せぬエラー: \(error)")
}
}
enum ParsingError: Error {
case missingField
case invalidType
}
JSONSerializationは、無効なJSON、型の不一致、またはネスト深さを超えた場合にエラーをスローします。エラーはCocoaError型に属し、問題を説明するコードを含みます。開発者はdo-catch構造を使ってこれらを処理する必要があり、そうしないとアプリケーションがクラッシュします。最もよくあるエラーは、NSPropertyListReadCorruptError(無効なJSON)とNSPropertyListReadUnknownErrorです。各エラー型には独自の処理策が必要です。無効な形式の場合はデータの再送信をリクエストし、構造の不一致の場合は解析モデルを更新します。
無効なJSON—フォーマットが正しくないために発生する最もよくある問題です。カンマの違い、余分な文字、エスケープされていない引用符などが原因です。2番目のタイプは、予期されていた構造との不一致です。例えば、サーバーが辞書の代わりに配列を返した場合です。JSONSerialization.fragmentsAllowedは、ルートが辞書や配列ではなくプリミティブ値であるJSONを読み取ることを可能にします。また、JSONがあまりに多くの階層レベルを含む場合、ネスト深さ超過エラーが発生することがあります。
JSONSerializationは、解析を構成するためのいくつかのオプションを提供します。.mutableContainersは不変バージョンの代わりにNSMutableDictionaryとNSMutableArrayを返し、解析後のデータ変更に役立ちます。.mutableLeavesは文字列値を変更可能にします。.fragmentsAllowedは、ルートがオブジェクトや配列ではなく、文字列または数値であるJSONを許可し、簡単なAPI応答に便利です。.withoutEscapingSlashesと.sortedKeysオプションはdata(withJSONObject:options:)メソッドに利用可能で、シリアライズされたJSONのフォーマットを制御します。オプションはビットマスクとして渡され、| 演算子で複数の値を組み合わせて柔軟な解析構成が可能です。
// 様々なタイプのエラー処理
func safeParse(jsonData: Data) {
do {
let object = try JSONSerialization
.jsonObject(with: jsonData,
options: .fragmentsAllowed)
if let dictionary = object as? [String: Any] {
print("\(dictionary.count)キーの辞書")
} else if let array = object as? [Any] {
print("\(array.count)アイテムの配列")
}
} catch CocoaError.propertyListReadCorrupt {
print("損傷したJSONデータ")
} catch let error as CocoaError {
print("Cocoaエラー: \(error)")
} catch {
print("不明なエラー: \(error)")
}
}
// シリアライズ前のオブジェクトの有効性確認
let testObject: [String: Any] = ["key": "value", "nested": ["a": 1]]
if JSONSerialization.isValidJSONObject(testObject) {
print("有効なJSONオブジェクト")
}
JSONSerializationのパフォーマンスは、データサイズとコール頻度に依存します。小さなサーバー応答の単一解析では差はほとんどありませんが、数10MBのJSONやループ内での頻繁なコールを処理する場合は、型キャストのオーバーヘッドを考慮する必要があります。JSONSerializationは現在のスレッドで同期的に動作します。そのため、大きなドキュメントの場合は、DispatchQueue.global()を使って解析をバックグラウンドキューに移すことをおすすめします。代替方法として、全ファイルをメモリにロードせずにストリーミング処理するためにInputStreamを使用できます。これは資源制約のあるアプリケーションで重要です。ファイルまたはネットワークストリームにJSONを書き込む場合、writeJSONObject(_:to:options:error:)メソッドを使用すると、中間Dataオブジェクトを作成せずに直接OutputStreamにシリアライズデータを送信でき、大きなドキュメントを操作する際のメモリ消費を削減できます。
よくある質問
JSONSerializationは、JSON DataをFoundationオブジェクト(NSDictionary、NSArray)に変換したり、その逆を行うFoundationクラスです。追加ライブラリなしでiOS、macOS、tvOS、watchOSで動作します。
Codableは、型安全なコードにコンパイルされる自動的な型指定シリアライゼーションのためのSwiftプロトコルです。JSONSerializationは動的なAny型を操作し、手動キャストが必要です。新しいプロジェクトにはCodable、Objective-Cや動的なデータにはJSONSerializationが適しています。
jsonObjectを呼ぶ際に、do-catch構造を使用します。JSONSerializationのエラーはCocoaErrorに属します。デバッグ時には、無効なJSONデータ形式を示すNSPropertyListReadCorruptErrorを確認してください。
はい、JSONSerializationは辞書や配列のあらゆるネスト深さをサポートしています。すべてのネストオブジェクトは、対応するFoundation型(NSDictionary、NSArray、NSString、NSNumber)に変換され、元のJSON構造を保持します。
JSONSerializationは、動的なJSON構造、Objective-Cプロジェクト、ストリーム操作、およびisValidJSONObjectによるJSON検証に適しています。スキーマが決まっている型指定構造には、Codableが適しています。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。