質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

2回答

1852閲覧

【Swift】JSONデータの取得方法が分からない

ysda

総合スコア65

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2019/12/12 07:08

前提・実現したいこと

TeratailのAPIを使って、質問内容などを表示させるアプリを作成したいと考えております。
TeratailのJSONから取得したいもののみを取ってくる方法が分からず、悩んでおります。
ご教示いただければと思います。

発生している問題

取得したいJSON

{ meta = { "hit_num" = 226005; limit = 20; message = success; page = 1; "total_page" = 11301; }; questions = ( { "count_clip" = 0; "count_pv" = 0; "count_reply" = 0; created = "2019-12-12 15:53:38"; id = 229063; "is_accepted" = 0; "is_beginner" = 1; "is_presentation" = 0; modified = "2019-12-12 15:53:38"; tags = ( YOLO ); title = "Yolov3\U3067\U30aa\U30ea\U30b8\U30ca\U30eb\U306e\U5b66\U7fd2\U306e\U4ed5\U65b9\U6559\U3048\U3066\U304f\U308c\U307e\U305b\U3093\U304b"; user = { "display_name" = "tigreon.0102"; photo = "https://teratail-v2.storage.googleapis.com/uploads/avatars/u13/134972/KhYLyYBS_thumbnail.jpg"; score = 1;                      〜〜〜長いので以下省略〜〜〜

こちらのJSONから、questions内のtitleを取得したいのですが、その方法が分からず、悩んでおります。

試したこと

以下の関数を使用して、["meta"]["questions"]をkey値にもつDictionary型は作れたのですが、さらにその中にあるvalueから該当部分のみを抽出する(今回の場合は、questions内のtitle)には、どのようにすればよろしいのでしょうか?
また、そもそもこの方法では該当部分を取り出すことはできないのでしょうか?

ご教示いただけると幸いです。

swift

1 2//GetTeratail.swift 3 4import Foundation 5 6struct getTeratailJson { 7 static func fetchQuestion(){ 8 guard let url = URL(string: "https://teratail.com/api/v1/questions") else {return} 9 let task = URLSession.shared.dataTask(with: url) { (data, response, error) in 10 11 do { 12 guard let data = data else {return} 13 let json = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.allowFragments) as! [String:Any] 14 print(json["questions"]!) 15 } 16 catch { 17 print("error:", error) 18 } 19 } 20 task.resume() 21 } 22}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

Playground専用のサンプルです。
JSONの使い方は簡単になりました:

swift

1let json = try JSONDecoder().decode(Teratail.self, from: data)

こうすれば、「ドット表記」でなんでも簡単に取得する事ができます。

swift

1import Foundation 2 3 func fetchQuestion(){ 4 guard let url = URL(string: "https://teratail.com/api/v1/questions") else {return} 5 let task = URLSession.shared.dataTask(with: url) { (data, response, error) in 6 7 do { 8 guard let data = data else {return} 9 10 let json = try JSONDecoder().decode(Teratail.self, from: data) 11 for question in json.questions { 12 print(question.tags) 13 } 14 } 15 catch { 16 print("error:", error) 17 } 18 } 19 task.resume() 20 } 21 22struct Teratail: Decodable { 23 let meta: Meta 24 let questions: [Question] 25} 26 27struct Meta: Decodable { 28 let hit_num: Int 29 let limit: Int 30 let message: String 31 let page: Int 32 let total_page: Int 33} 34 35struct Question : Decodable { 36 let count_clip: Int 37 let count_pv : Int 38 let count_reply: Int 39 let created: String 40 let modified: String 41 let id: Int 42 let is_accepted: Bool 43 let is_beginner: Bool 44 let is_presentation: Bool 45 let tags: [String] 46 let title: String 47 let user: User 48} 49 50struct User: Decodable { 51 let display_name: String 52 let photo: String 53 let score: Int 54} 55 56fetchQuestion() 57

投稿2019/12/12 07:53

vanderlvov

総合スコア685

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ysda

2019/12/12 08:05

ご回答ありがとうございます。 型キャストを駆使してやろうとしていたのですが、最初からデータを入れる箱を作ればよかったのですね。 検索しても思うようにうまくいかなかったのですが、一発で解決できました。 とても助かりました!
guest

0

おそらく

swift

1if let questions = json["questions"] as? [String: Any] { 2 print(questions["value"]) 3}

などと書けば出ると思いますが、
SwiftyJSONならばもう少し簡単にアクセスできるようですし、
ほぼ決まった型でしたら、Codableの機能を使ってパースするのも手です。

投稿2019/12/12 07:54

takabosoft

総合スコア8356

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ysda

2019/12/12 08:14

ご回答ありがとうございます。 JSONの取得方法のロジックを勉強するために、あえてライブラリを使わずに作ってみようと思ってSwiftyJSONには手を出さずにやってみました。
takabosoft

2019/12/12 08:24 編集

vanderlvovさんが回答されている方法がSwift4辺りから追加されたCodableの機能です。 これが一番楽なので、この方法が採れるのでしたら、まずは最優先でCodableでいいと思います。 ただ、Swiftの入れ子になっているDictionary型の中を探索する方法は知っておいて損はないので、 私の回答した方法も一度は試しておくことをおすすめします。 回答欄には"value"と書きましたが、titleであれば if let questions = json["questions"] as? [String: Any] { print(questions["title"] as? string) } などとすれば取れると思われます。
ysda

2019/12/12 08:39

ご助言までいただきましてありがとうございます! そうですね、まずはCodableの使用方法を優先に勉強していきます。 またご回答いただいた方法も一つの手段として活用していこうと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問