現在下記の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() }
「レスポンスを受け取る」というのは、具体的には何をすることを意味していますか?
「レスポンスを受け取る」という言葉から、ネット上のAPIに特定のパラメータでアクセスして、データを受け取る、というようなやり取りを想像するのですが、相手がJSON形式のデータなので意味が想像できません。
そもそも、JSON1 の形式間違っていますし、Model1 の構造も間違っているようです。
変換サイトを使ってモデル(構造体)を作られているようですが、試しに JSON1 としてあげられた JSON1 をその変換サイトで変換してみてはいかがでしょうか。おそらくパースエラーとなって分析できないはずです(私は2つのサイトで試しましたが、やはりパースエラーとなりました)。
JSON にしても、返還後のモデルにしても、構造を把握しきれていないうちは無闇に手を加えないのが良いかと思います。
APIにリクエストをして、レスポンスされた情報をjson形式で表示する。が正しいです。
JSONから受け取るとは不可解でした。
そうですね、形式も構造も違っていました。すみません。
確認して再度必要な物を絞って変更しました。
こちらは変換が可能です。
そうなると、問題は解決したように思えるのですが、いかがでしょうか。
Model2 と同じような流れでJSONを受け取り、デコードすれば良いだけとなります。
Model2と同様に試してみたのですが
コード案でself.items.append(contentsOf: newMovies)のラインで
Cannot convert value of type '[Cast]' to expected argument type '[CastItem]'
となってしまいます。またCastだけでなくCreditsのCrewも受け取りたいので、どうすれば良いのでしょうか?
そもそも、取り出したい JSON の情報と取り出そうとしている型が一致していませんが、それは理解されていますでしょうか。
指定している URL から直接取り出せるのは struct CastModel に相当する情報ですが、入れ子になっている情報は一括して取り出せます。まずは CastModel で取り出してから、その中の情報にアクセスすることになりますが、それはご理解いただけますでしょうか。
すみません、型もURLも違うまま記載しまいました。CastModelに修正しました。
つまりCastModelをdecodeすれば一旦Modelで指定した情報は取得できるため
その後そのデータを変換して代入すれば質問で記入したエラーも出ずに思うように使用できるという事ですか?
それでいいかと思います(まずは、やってみてエラーが出るか試すのが重要かと思います)。
最終的には
let newMovies = finalResult.credits.cast
みたいな感じで必要なデータだけ取り出してみてはいかがでしょうか。
そうですね、試してみます。
丁寧なご回答ありがとうございました。
回答1件
あなたの回答
tips
プレビュー