サーチ…


構文

  • NSJSONSerialization.JSONObjectWithData(jsonData、options:NSJSONReadingOptions)// jsonDataからオブジェクトを返します。このメソッドは失敗時にスローされます。
  • NSJSONSerialization.dataWithJSONObject(jsonObject、options:NSJSONWritingOptions)// JSONオブジェクトからNSDataを返します。 NSJSONWritingOptions.PrettyPrintedに、より読みやすい出力オプションを渡してください。

Apple FoundationとSwift標準ライブラリを使用したJSONシリアライズ、エンコーディング、デコード

JSONSerializationクラスは、AppleのFoundationフレームワークに組み込まれています。

2.2

JSONを読む

JSONObjectWithData機能がかかるNSData 、と返しAnyObject 。あなたはas?結果をあなたの予想されるタイプに変換します。

do {
    guard let jsonData = "[\"Hello\", \"JSON\"]".dataUsingEncoding(NSUTF8StringEncoding) else {
        fatalError("couldn't encode string as UTF-8")
    }

    // Convert JSON from NSData to AnyObject
    let jsonObject = try NSJSONSerialization.JSONObjectWithData(jsonData, options: [])
    
    // Try to convert AnyObject to array of strings
    if let stringArray = jsonObject as? [String] {
        print("Got array of strings: \(stringArray.joinWithSeparator(", "))")
    }
} catch {
    print("error reading JSON: \(error)")
}

options: []代わりにoptions: .AllowFragmentsを渡すことで、トップレベルのオブジェクトが配列や辞書でないときにJSONを読み取ることができます。

JSONを書く

dataWithJSONObject呼び出すと、JSON互換のオブジェクト(ネストされた配列または文字列、数値、 NSNull持つ辞書)がUTF-8としてエンコードされた生のNSDataされます。

do {
    // Convert object to JSON as NSData
    let jsonData = try NSJSONSerialization.dataWithJSONObject(jsonObject, options: [])
    print("JSON data: \(jsonData)")
    
    // Convert NSData to String
    let jsonString = String(data: jsonData, encoding: NSUTF8StringEncoding)!
    print("JSON string: \(jsonString)")
} catch {
    print("error writing JSON: \(error)")
}

options: .PrettyPrintedを渡すことができoptions: .PrettyPrinted代わりにoptions: .PrettyPrinted options: [] 、かわいい印刷用。

3.0

Swift 3でも同じ構文ですが、構文が異なります。

do {
    guard let jsonData = "[\"Hello\", \"JSON\"]".data(using: String.Encoding.utf8) else {
        fatalError("couldn't encode string as UTF-8")
    }
    
    // Convert JSON from NSData to AnyObject
    let jsonObject = try JSONSerialization.jsonObject(with: jsonData, options: [])
    
    // Try to convert AnyObject to array of strings
    if let stringArray = jsonObject as? [String] {
        print("Got array of strings: \(stringArray.joined(separator: ", "))")
    }
} catch {
    print("error reading JSON: \(error)")
}

do {
    // Convert object to JSON as NSData
    let jsonData = try JSONSerialization.data(withJSONObject: jsonObject, options: [])
    print("JSON data: \(jsonData)")

    // Convert NSData to String
    let jsonString = String(data: jsonData, encoding: .utf8)!
    print("JSON string: \(jsonString)")
} catch {
    print("error writing JSON: \(error)")
}

注:以下は、現在Swift 4.0以降でのみ利用可能です。

Swift 4.0以降、Swift標準ライブラリには、データのエンコードとデコードに対する標準化されたアプローチを定義するためのプロトコルEncodableDecodableが含まれています。これらのプロトコルを採用することで、 EncoderおよびDecoderプロトコルの実装でデータを取得し、JSONなどの外部表現との間でエンコードまたはデコードすることができます。適合Codableプロトコルは両方兼ね備えEncodableDecodableプロトコルを。これは、プログラムでJSONを処理するための推奨手段です。

自動的にエンコードとデコード

型コーディング可能なコードを作成する最も簡単な方法は、そのプロパティを既にCodable可能な型として宣言することCodable 。これらの型には、 StringIntDoubleなどの標準ライブラリ型が含まれます。およびDateDataURLなどの基盤型がありURL 。型のプロパティがコード化可能な場合、型自体は単に型を宣言するだけで自動的にCodableに適合します。

Book構造がCodable準拠している次の例を考えてみましょう。

struct Book: Codable {
    let title: String
    let authors: [String]
    let publicationDate: Date
}

ArrayDictionaryなどの標準的なコレクションは、コード可能な型を含む場合、 Codable準拠していることに注意してください。

採用することによりCodableBook構造は今にエンコードすることができ、アップル財団クラス使用してJSONからデコードJSONEncoderJSONDecoderにもかかわらず、 Book自体は特にJSONを処理するための何のコードが含まれていません。カスタムエンコーダおよびデコーダは、それぞれ、 EncoderおよびDecoderプロトコルに準拠して記述することもできる。

JSONデータにエンコードする

// Create an instance of Book called book
let encoder = JSONEncoder()
let data = try! encoder.encode(book) // Do not use try! in production code
print(data)

読みやすいようにencoder.outputFormatting = .prettyPrintedを設定します。 ## JSONデータからのデコード

JSONデータからのデコード

// Retrieve JSON string from some source
let jsonData = jsonString.data(encoding: .utf8)!
let decoder = JSONDecoder()
let book = try! decoder.decode(Book.self, for: jsonData) // Do not use try! in production code
print(book)

上記の例では、 Book.selfはJSONをデコードする型をデコーダに通知します。

エンコードまたはデコード専用

場合によっては、APIからJSONデータのみを読み込む必要がある場合や、プログラムがJSONデータをAPIに送信する場合など、データをエンコード可能とデコード可能にする必要はありません。

JSONデータのみを書きたい場合は、タイプをEncodable合わせます。

struct Book: Encodable {
    let title: String
    let authors: [String]
    let publicationDate: Date
}

JSONデータの読み取りのみを目的とする場合は、タイプをDecodableます。

struct Book: Decodable {
    let title: String
    let authors: [String]
    let publicationDate: Date
}

カスタムキー名の使用

APIは、スネークケースのようなSwift標準のラクダケース以外の命名規則を頻繁に使用します。デフォルトでJSONキーは型のプロパティ名と正確に一致する必要があるので、これはJSONのデコードに関しては問題になる可能性があります。これらのシナリオを処理するには、 CodingKeyプロトコルを使用してCodingKeyタイプのカスタムキーを作成します。

struct Book: Codable {
    // ...
    enum CodingKeys: String, CodingKey { 
        case title
        case authors
        case publicationDate = "publication_date"
    }
}

CodingKeysプロトコルを採用するタイプのCodingKeysが自動的に生成されますが、上記の例で独自の実装を作成することで、デコーダがローカルCodableケースのpublicationDateをAPIによって配信されたsnakeケースのpublication_dateに一致させることができます。

SwiftyJSON

SwiftyJSONは、通常のJSONシリアル化でのオプションの連鎖の必要性を取り除くために構築されたSwiftフレームワークです。

ここからダウンロードできます: https : //github.com/SwiftyJSON/SwiftyJSON

SwiftyJSONを使用しないと、コードはJSONオブジェクトの最初の本の名前を見つけるために次のようになります。

if let jsonObject = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments) as? [[String: AnyObject]],
let bookName = (jsonObject[0]["book"] as? [String: AnyObject])?["name"] as? String {
    //We can now use the book name
}

SwiftyJSONでは、これは非常に簡単です:

let json = JSON(data: data)
if let bookName = json[0]["book"]["name"].string {
    //We can now use the book name
}

それらが無効な場合はnilを返すので、すべてのフィールドをチェックする必要はありません。

SwiftyJSONを使用するには、Gitリポジトリから適切なバージョンをダウンロードします。Swift 3のブランチがあります。 "SwiftyJSON.swift"をプロジェクトにドラッグしてクラスにインポートするだけです:

import SwiftyJSON

次の2つのイニシャライザを使用してJSONオブジェクトを作成できます。

let jsonObject = JSON(data: dataObject)

または

let jsonObject = JSON(jsonObject) //This could be a string in a JSON format for example

データにアクセスするには、下付き文字を使用します。

let firstObjectInAnArray = jsonObject[0]
let nameOfFirstObject = jsonObject[0]["name"]

次に、値を特定のデータ型に解析して、オプションの値を返します。

let nameOfFirstObject = jsonObject[0]["name"].string //This will return the name as a string

let nameOfFirstObject = jsonObject[0]["name"].double //This will return null

また、パスを迅速な配列にコンパイルすることもできます。

let convolutedPath = jsonObject[0]["name"][2]["lastName"]["firstLetter"].string

同じです:

let convolutedPath = jsonObject[0, "name", 2, "lastName", "firstLetter"].string

SwiftyJSONには、独自のエラーを出力する機能もあります。

if let name = json[1337].string {
    //You can use the value - it is valid
} else {
    print(json[1337].error) // "Array[1337] is out of bounds" - You cant use the value
}

JSONオブジェクトに書き込む必要がある場合は、添字を再度使用できます。

var originalJSON:JSON = ["name": "Jack", "age": 18]
originalJSON["age"] = 25 //This changes the age to 25
originalJSON["surname"] = "Smith" //This creates a new field called "surname" and adds the value to it

JSONの元のStringが必要な場合(たとえば、ファイルに書き込む必要がある場合など)は、そのままの値を取得できます。

if let string = json.rawString() { //This is a String object
    //Write the string to a file if you like
}

if let data = json.rawData() { //This is an NSData object
    //Send the data to your server if you like
}

フレディ

FreddyBig Nerd Ranchが管理するJSON解析ライブラリです。それは3つの主な利点があります:

  1. 型の安全性:実行時のクラッシュを防止する方法でJSONを送受信する作業に役立ちます。

  2. イディオム:複雑な文書や魔法のカスタム演算子なしで、Swiftのジェネリック、列挙、および機能的な機能を利用します。

  3. エラー処理:一般的に発生するJSONエラーに関する有益なエラー情報を提供します。

JSONデータの例

これらの例で使用するJSONデータの例をいくつか定義しましょう。

{
  "success": true,
  "people": [
    {
      "name": "Matt Mathias",
      "age": 32,
      "spouse": true
    },
    {
      "name": "Sergeant Pepper",
      "age": 25,
      "spouse": false
    }
  ],
  "jobs": [
    "teacher",
    "judge"
  ],
  "states": {
    "Georgia": [
      30301,
      30302,
      30303
    ],
    "Wisconsin": [
      53000,
      53001
    ]
  }
}
let jsonString = "{\"success\": true, \"people\": [{\"name\": \"Matt Mathias\",\"age\": 32,\"spouse\": true},{\"name\": \"Sergeant Pepper\",\"age\": 25,\"spouse\": false}],\"jobs\": [\"teacher\",\"judge\"],\"states\": {\"Georgia\": [30301,30302,30303],\"Wisconsin\": [53000,53001]}}"
let jsonData = jsonString.dataUsingEncoding(NSUTF8StringEncoding)!

生データのデシリアライズ

データをデシリアライズするには、 JSONオブジェクトを初期化して特定のキーにアクセスします。

do {
    let json = try JSON(data: jsonData)
    let success = try json.bool("success")
} catch {
    // do something with the error
}

我々はtryアクセスするので、ここでjsonキーに"success"それが存在しないか、または値がブール値ではないかもしれない-失敗する可能性があります。

また、JSON構造体にネストされた要素にアクセスするためのパスを指定することもできます。パスは、関心のある値へのパスを記述するキーとインデックスのコンマ区切りのリストです。

do {
    let json = try JSON(data: jsonData)
    let georgiaZipCodes = try json.array("states", "Georgia")
    let firstPersonName = try json.string("people", 0, "name")
} catch {
    // do something with the error
}

直接モデルの逆シリアル化

JSONは、 JSONDecodableプロトコルを実装するモデルクラスに直接解析できます。

public struct Person {
    public let name: String
    public let age: Int
    public let spouse: Bool
}

extension Person: JSONDecodable {
    public init(json: JSON) throws {
        name = try json.string("name")
        age = try json.int("age")
        spouse = try json.bool("spouse")
    }
}

do {
    let json = try JSON(data: jsonData)
    let people = try json.arrayOf("people", type: Person.self)
} catch {
    // do something with the error
}

生データのシリアル化

どのJSON値もNSData直接シリアル化できます。

let success = JSON.Bool(false)
let data: NSData = try success.serialize()

直接モデルのシリアライズ

実装するすべてのモデルクラスJSONEncodableプロトコルは、直接シリアライズすることができNSData

extension Person: JSONEncodable {
    public func toJSON() -> JSON {
        return .Dictionary([
            "name": .String(name),
            "age": .Int(age),
            "spouse": .Bool(spouse)
        ])
    }
}

let newPerson = Person(name: "Glenn", age: 23, spouse: true)
let data: NSData = try newPerson.toJSON().serialize()

矢印

Arrowは、Swiftの洗練されたJSON解析ライブラリです。

JSONを解析して、 <--演算子の助けを借りてカスタムモデルクラスにマップすることができます:

identifier <-- json["id"]
name <-- json["name"]
stats <-- json["stats"]

例:

スウィフトモデル

struct Profile {
    var identifier = 0
    var name = ""
    var link: NSURL?
    var weekday: WeekDay = .Monday
    var stats = Stats()
    var phoneNumbers = [PhoneNumber]()
}

JSONファイル

{
    "id": 15678,
    "name": "John Doe",
    "link": "https://apple.com/steve",
    "weekdayInt" : 3,
    "stats": {
        "numberOfFriends": 163,
        "numberOfFans": 10987
    },
    "phoneNumbers": [{
                     "label": "house",
                     "number": "9809876545"
                     }, {
                     "label": "cell",
                     "number": "0908070656"
                     }, {
                     "label": "work",
                     "number": "0916570656"
    }]
}

マッピング

extension Profile: ArrowParsable {
    mutating func deserialize(json: JSON) {
        identifier <-- json["id"]
        link <-- json["link"]
        name <-- json["name"]
        weekday <-- json["weekdayInt"]
        stats <- json["stats"]
        phoneNumbers <-- json["phoneNumbers"]
    }
}

使用法

let profile = Profile()
profile.deserialize(json)

インストール:

カーセージ

github "s4cha/Arrow"

ココアポッド

pod 'Arrow'
use_frameworks!

手動で

あなたのXcodeプロジェクトにArrow.swiftをコピー&ペーストするだけです

https://github.com/s4cha/Arrow

フレームワークとして

GitHubリポジトリからArrowをダウンロードし、サンプルプロジェクトでFrameworkターゲットをビルドします 。次に、このフレームワークとリンクします。

カスタムオブジェクトへの単純なJSON解析

サードパーティ製のライブラリが良好であっても、JSONをパースするための簡単な方法は、あなたがオブジェクト持っているあなたが想像できるプロトコルによって提供されTodoなどを

struct Todo {
    let comment: String
}

JSONを受け取るたびに、 NSJSONSerializationオブジェクトを使用して、他の例に示すようにプレーンなNSDataを処理できます。

その後、単純なプロトコルJSONDecodableを使用して

typealias JSONDictionary = [String:AnyObject]
protocol JSONDecodable {
    associatedtype Element
    static func from(json json: JSONDictionary) -> Element?
}

そして、あなたのTodo構造体をJSONDecodable準拠さJSONDecodableことがトリックになります

extension Todo: JSONDecodable {
    static func from(json json: JSONDictionary) -> Todo? {
        guard let comment = json["comment"] as? String else { return nil }
        return Todo(comment: comment)
    }
}

あなたはこのjsonコードで試すことができます:

{
    "todos": [
        {
            "comment" : "The todo comment"
        }
    ]
}

APIから取得した場合は、前の例のようにAnyObjectインスタンスにAnyObjectます。その後、インスタンスがJSONDictionaryインスタンスかどうかを確認できます

guard let jsonDictionary = dictionary as? JSONDictionary else { return }

JSONにTodo配列があるため、このケースに固有のチェックするもう1つの点は、 todos辞書です

guard let todosDictionary = jsonDictionary["todos"] as? [JSONDictionary] else { return }

これで、辞書の配列が得られたので、 flatMapを使ってTodoオブジェクトのそれぞれを変換することができます(配列からnil値が自動的に削除されます)

let todos: [Todo] = todosDictionary.flatMap { Todo.from(json: $0) }

JSON解析スウィフト3

ここで使用するJSONファイルはanimals.json

{
    "Sea Animals": [
    {
     "name": "Fish",
     "question": "How many species of fish are there?"    },
                {
                "name": "Sharks",
                "question": "How long do sharks live?"
                },
                {
                "name": "Squid",
                "question": "Do squids have brains?"
                },
                {
                "name": "Octopus",
                "question": "How big do octopus get?"
                },
                {
                "name": "Star Fish",
                "question": "How long do star fish live?"
                }
                ],
    "mammals": [
                {
      "name": "Dog",
      "question": "How long do dogs live?"
    },
    {
      "name": "Elephant",
      "question": "How much do baby elephants weigh?"
    },
    {
      "name": "Cats",
      "question": "Do cats really have 9 lives?"
    },
    {
      "name": "Tigers",
      "question": "Where do tigers live?"
    },
    {
      "name": "Pandas",
      "question": "WHat do pandas eat?"
    }   ] }

プロジェクトでJSONファイルをインポートする

この単純な関数を実行すると、JSONファイルを出力できます

   func jsonParsingMethod() {
        //get the file
        let filePath = Bundle.main.path(forResource: "animals", ofType: "json")
        let content = try! String(contentsOfFile: filePath!)
        
        let data: Data = content.data(using: String.Encoding.utf8)!
        let json: NSDictionary =  try! JSONSerialization.jsonObject(with: data as Data, options:.mutableContainers) as! NSDictionary
      
//Call which part of the file you'd like to pare
        if let results = json["mammals"] as? [[String: AnyObject]] {
            
            for res in results {
                //this will print out the names of the mammals from out file.
                if let rates = res["name"] as? String {
                    print(rates)
                }
           }
       }
    }

テーブルビューに配置したい場合は、まずNSObjectを使って辞書を作成します。

ParsingObjectというParsingObject新しいファイルを作成し、文字列変数を作成します。

変数名がJSONファイルと同じであることを確認してください

。たとえば、私たちのプロジェクトではnamequestionがありquestionので、新しい素早いファイルでは、

var name: String?
var question: String?

ViewController.swiftに戻したNSObjectを初期化します。var array = ParsingObjectその後、マイナーな変更を加えて以前と同じメソッドを実行します。

     func jsonParsingMethod() {
            //get the file
            let filePath = Bundle.main.path(forResource: "animals", ofType: "json")
            let content = try! String(contentsOfFile: filePath!)
            
            let data: Data = content.data(using: String.Encoding.utf8)!
            let json: NSDictionary =  try! JSONSerialization.jsonObject(with: data as Data, options:.mutableContainers) as! NSDictionary
            
//This time let's get Sea Animals
            let results = json["Sea Animals"] as? [[String: AnyObject]]
            
//Get all the stuff using a for-loop
            for i in 0 ..< results!.count {
                
//get the value
                let dict = results?[i]
                let resultsArray = ParsingObject()
                
//append the value to our NSObject file
                resultsArray.setValuesForKeys(dict!)
                array.append(resultsArray)
                
            }
          
        }

次に、これを行うことでテーブルビューに表示します。

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return array.count
        }
        
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
//This is where our values are stored
            let object = array[indexPath.row]
            cell.textLabel?.text = object.name
            cell.detailTextLabel?.text = object.question
            return cell
        }


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow