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

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

新規登録して質問してみよう
ただいま回答率
85.48%
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

解決済

1回答

1273閲覧

複雑なJSON形式でAPIで取得したデータを表示する方法

secretUsed

総合スコア2

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クリップ

投稿2020/11/13 15:44

編集2020/11/17 14:34

現在下記のJSON1からレスポンスを受け取るためのModelをサイトから自動で作り、
取得したいdataだけ残しました。
JSON2では下記のようにレスポンスを受け取ったのですがJSON1ではCastとCrewはCreditsの配列に入っているので、どうViewControllerではレスポンスを受け取れば良いのかと思ったのでご教授願いたいです。


JSON1

{ "id": 597, "credits": { "cast": [ { "id": 6193, "name": "Leonardo DiCaprio" } ], "crew": [ { "department": "Directing", "id": 2710, "job": "Director", "name": "James Cameron" } ] } }

Model1

import Foundation // MARK: - Welcome struct CastModel: Codable { let id: Int let credits: Credits } // MARK: - Credits struct Credits: Codable { let cast: [Cast] let crew: [Crew] } // MARK: - Cast struct Cast: Codable { let id: Int let name: String } // MARK: - Crew struct Crew: Codable { let department: String let id: Int let job, name: String }

JSON2 & Model2

//JSON { "results": [ { "id": 597, "title": "タイタニック", "release_date": "1997-11-18", "original_language": "en", "original_title": "Titanic", "overview": "poster_path": "/9THZ0bjPRc4qP229dmItJcQTQKU.jpg" }, ] } -------------------------------------------------------- //Model import Foundation struct MovieItem : Codable { let id:Int let title: String let release_date:String? let poster_path:String? let overview:String? let original_language:String? } struct MovieStruct: Codable { let results: [MovieItem] }
class FirstViewController: UIViewController { @IBOutlet weak var table: UITableView! private var items:[MovieItem] = [MovieItem]() override func viewDidLoad() { super.viewDidLoad() fechData() } func fechData(){ items.removeAll() URLSession.shared.dataTask(with: URL(string: "https://api.themoviedb.org/3/movie/popular?api_key=########&language=ja&page=1")!, completionHandler: {data, response, error in guard let data = data else { print(error?.localizedDescription ?? "Unknown error") return } var result: MovieStruct? do { result = try JSONDecoder().decode(MovieStruct.self, from: data) } catch{ print("JSON perse error") } guard let finalResult = result else { return } let newMovies = finalResult.results self.items.append(contentsOf: newMovies) DispatchQueue.main.async { self.table.reloadData() } }).resume() } }

コード案

private var items:[CastModel] = [CastModel]() func fechData(){ items.removeAll() //movieIDは他のVIewControllerか取得したものとなります。 URLSession.shared.dataTask(with: URL(string: "https://api.themoviedb.org/3/movie/(movieID)?api_key=#########&language=ja&append_to_response=credits")!, completionHandler: {data, response, error in guard let data = data else { print(error?.localizedDescription ?? "Unknown error") return } var result: Credits? do { result = try JSONDecoder().decode(Credits.self, from: data) } catch { print("JSON perse error") } guard let finalResult = result else { return } let newMovies = finalResult.cast self.items.append(contentsOf: newMovies) print(newMovies) DispatchQueue.main.async { self.table.reloadData() } }).resume() }

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

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

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

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

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

coco_bauer

2020/11/14 01:30

「レスポンスを受け取る」というのは、具体的には何をすることを意味していますか? 「レスポンスを受け取る」という言葉から、ネット上のAPIに特定のパラメータでアクセスして、データを受け取る、というようなやり取りを想像するのですが、相手がJSON形式のデータなので意味が想像できません。
TsukubaDepot

2020/11/14 02:25

そもそも、JSON1 の形式間違っていますし、Model1 の構造も間違っているようです。 変換サイトを使ってモデル(構造体)を作られているようですが、試しに JSON1 としてあげられた JSON1 をその変換サイトで変換してみてはいかがでしょうか。おそらくパースエラーとなって分析できないはずです(私は2つのサイトで試しましたが、やはりパースエラーとなりました)。 JSON にしても、返還後のモデルにしても、構造を把握しきれていないうちは無闇に手を加えないのが良いかと思います。
secretUsed

2020/11/14 04:04

APIにリクエストをして、レスポンスされた情報をjson形式で表示する。が正しいです。 JSONから受け取るとは不可解でした。
secretUsed

2020/11/14 04:04

そうですね、形式も構造も違っていました。すみません。 確認して再度必要な物を絞って変更しました。 こちらは変換が可能です。
TsukubaDepot

2020/11/14 04:05

そうなると、問題は解決したように思えるのですが、いかがでしょうか。 Model2 と同じような流れでJSONを受け取り、デコードすれば良いだけとなります。
secretUsed

2020/11/14 05:04 編集

Model2と同様に試してみたのですが コード案でself.items.append(contentsOf: newMovies)のラインで Cannot convert value of type '[Cast]' to expected argument type '[CastItem]' となってしまいます。またCastだけでなくCreditsのCrewも受け取りたいので、どうすれば良いのでしょうか?
TsukubaDepot

2020/11/14 10:56

そもそも、取り出したい JSON の情報と取り出そうとしている型が一致していませんが、それは理解されていますでしょうか。 指定している URL から直接取り出せるのは struct CastModel に相当する情報ですが、入れ子になっている情報は一括して取り出せます。まずは CastModel で取り出してから、その中の情報にアクセスすることになりますが、それはご理解いただけますでしょうか。
secretUsed

2020/11/14 11:55

すみません、型もURLも違うまま記載しまいました。CastModelに修正しました。 つまりCastModelをdecodeすれば一旦Modelで指定した情報は取得できるため その後そのデータを変換して代入すれば質問で記入したエラーも出ずに思うように使用できるという事ですか?
TsukubaDepot

2020/11/14 11:57

それでいいかと思います(まずは、やってみてエラーが出るか試すのが重要かと思います)。 最終的には let newMovies = finalResult.credits.cast みたいな感じで必要なデータだけ取り出してみてはいかがでしょうか。
secretUsed

2020/11/14 13:46

そうですね、試してみます。 丁寧なご回答ありがとうございました。
guest

回答1

0

自己解決

TsukubaDepot様から教えて頂いたことを参考に最終的にこちらで取得できたので
完成形を他の方用にまとめます。

import Foundation struct CastModel: Codable { let id: Int let credits: Credits } struct Credits: Codable { let cast: [Cast] let crew: [Crew] } struct Cast: Codable { let id: Int let name: String } struct Crew: Codable { let department: String let id: Int let job, name: String }
private var castItems:[Credits] = [Credits]() func fechData(){ castItems.removeAll() URLSession.shared.dataTask(with: URL(string: "https://api.themoviedb.org/3/movie/635302?api_key=########&language=ja&append_to_response=credits")!, completionHandler: {data, response, error in guard let data = data else { print(error?.localizedDescription ?? "Unknown error") return } var creditsResult: CastModel? do { creditsResult = try JSONDecoder().decode(CastModel.self, from: data) } catch { print("JSON perse error") } guard let finalResult = creditsResult else { return } let newMovies = finalResult.credits self.castItems.append(newMovies) print(newMovies) DispatchQueue.main.async { } }).resume() } }

投稿2020/11/17 14:29

secretUsed

総合スコア2

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問