TransWikia.com

JSONのレスポンスを格納したい

スタック・オーバーフロー Asked by uta on December 28, 2021

やりたいこと

JSONのレスポンスをStructにCodableを使いまとめてTableViewにString型として表示したい。

疑問点&エラー

var movies = MovieStruct() Missing argument for parameter 'from' in call(insert 'from' <#Decoder#>)

と表示されます。元々は

var movies = [MovieStruct]()

上記のように配列に入れていたのですがAPIのRequestしたところ配列(辞書型?)にはなっておらず全て{}で返ってきていたため
上手く表示されておらずdecodeも配列で返すのを直したのですがmoviesに構造体からきたデータを格納したいのですが
記述の仕方があまりよく分からず。調べても配列で返ってきているAPIの物ばかりなので質問しました。

ソースコード

import UIKit

class ViewController: UIViewController {
//https://api.themoviedb.org/3/movie/550?api_key=

    @IBOutlet weak var movieTableView: UITableView!
    
    var movies = MovieStruct()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        fechData()
    }
    
    func fechData(){

        let url = URL(string: "https://api.themoviedb.org/3/movie/550?api_key=")!
        URLSession.shared.dataTask(with: url) { (data, response, error) in
            guard let data = data else {
                print(error?.localizedDescription ?? "Unknown error")
                return
            }
            
            let decoder = JSONDecoder()
            
            if let movies = try? decoder.decode(MovieStruct.self, from: data){
                DispatchQueue.main.async {
//                    self.movies = movies
                    self.movies.append(movies)
                    self.movieTableView.reloadData()
                }
            }else{
                print("Unable parse JSON response")
            }
        }.resume()
    }
}

extension ViewController:UITableViewDelegate,UITableViewDataSource{
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return movies.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        let movie = movies[indexPath.row]
        
        cell.textLabel?.text = movie.title
        cell.detailTextLabel?.text = movie.release_date
        
        return cell
    }
}

struct MovieStruct: Codable {
    var title: String
    var release_date:String
}

レスポンス

{
    adult = 0;
    "backdrop_path" = "/8iVyhmjzUbvAGppkdCZPiyEHSoF.jpg";
    "belongs_to_collection" = "<null>";
    budget = 63000000;
    genres =     (
                {
            id = 18;
            name = Drama;
        }
    );
    homepage = "http://www.foxmovies.com/movies/fight-club";
    id = 550;
    "imdb_id" = tt0137523;
    "original_language" = en;
    "original_title" = "Fight Club";
    overview = "A ticking-time-bomb insomniac and a slippery soap salesman channel primal male aggression into a shocking new form of therapy. Their concept catches on, with underground "fight clubs" forming in every town, until an eccentric gets in the way and ignites an out-of-control spiral toward oblivion.";
    popularity = "39.218";
    "poster_path" = "/wR5HZWdVpcXx9sevV1bQi7rP4op.jpg";
    "production_companies" =     (
                {
            id = 508;
            "logo_path" = "/7PzJdsLGlR7oW4J0J5Xcd0pHGRg.png";
            name = "Regency Enterprises";
            "origin_country" = US;
        },
                {
            id = 711;
            "logo_path" = "/tEiIH5QesdheJmDAqQwvtN60727.png";
            name = "Fox 2000 Pictures";
            "origin_country" = US;
        },
                {
            id = 20555;
            "logo_path" = "/hD8yEGUBlHOcfHYbujp71vD8gZp.png";
            name = "Taurus Film";
            "origin_country" = DE;
        },
                {
            id = 54051;
            "logo_path" = "<null>";
            name = "Atman Entertainment";
            "origin_country" = "";
        },
                {
            id = 54052;
            "logo_path" = "<null>";
            name = "Knickerbocker Films";
            "origin_country" = US;
        },
                {
            id = 25;
            "logo_path" = "/qZCc1lty5FzX30aOCVRBLzaVmcp.png";
            name = "20th Century Fox";
            "origin_country" = US;
        },
                {
            id = 4700;
            "logo_path" = "/A32wmjrs9Psf4zw0uaixF0GXfxq.png";
            name = "The Linson Company";
            "origin_country" = "";
        }
    );
    "production_countries" =     (
                {
            "iso_3166_1" = DE;
            name = Germany;
        },
                {
            "iso_3166_1" = US;
            name = "United States of America";
        }
    );
    "release_date" = "1999-10-15";
    revenue = 100853753;
    runtime = 139;
    "spoken_languages" =     (
                {
            "iso_639_1" = en;
            name = English;
        }
    );
    status = Released;
    tagline = "Mischief. Mayhem. Soap.";
    title = "Fight Club";
    video = 0;
    "vote_average" = "8.4";
    "vote_count" = 19688;
}

One Answer

まず最初に、あなたが「レスポンス」として示されたのは実際のレスポンスではありません。どなたかが作られたプログラムで、レスポンスをNSDictionaryで読み込んだ後に、そのNSDictionaryををprintなどの形で出力したものと思われます。全く役に立たないわけではありませんが、元のJSONを完全には復元できないので、正しい回答を得るのには支障となる場合が多いです。

実際にレスポンスを取得して整形したものをお示ししておきます。

{
    "adult": false,
    "backdrop_path": "/8iVyhmjzUbvAGppkdCZPiyEHSoF.jpg",
    "belongs_to_collection": null,
    "budget": 63000000,
    "genres": [
        {
            "id": 18,
            "name": "Drama"
        }
    ],
    "homepage": "http://www.foxmovies.com/movies/fight-club",
    "id": 550,
    "imdb_id": "tt0137523",
    "original_language": "en",
    "original_title": "Fight Club",
    "overview": "A ticking-time-bomb insomniac and a slippery soap salesman channel primal male aggression into a shocking new form of therapy. Their concept catches on, with underground "fight clubs" forming in every town, until an eccentric gets in the way and ignites an out-of-control spiral toward oblivion.",
    "popularity": 34.634,
    "poster_path": "/wR5HZWdVpcXx9sevV1bQi7rP4op.jpg",
    "production_companies": [
        {
            "id": 508,
            "logo_path": "/7PzJdsLGlR7oW4J0J5Xcd0pHGRg.png",
            "name": "Regency Enterprises",
            "origin_country": "US"
        },
        {
            "id": 711,
            "logo_path": "/tEiIH5QesdheJmDAqQwvtN60727.png",
            "name": "Fox 2000 Pictures",
            "origin_country": "US"
        },
        {
            "id": 20555,
            "logo_path": "/hD8yEGUBlHOcfHYbujp71vD8gZp.png",
            "name": "Taurus Film",
            "origin_country": "DE"
        },
        {
            "id": 54051,
            "logo_path": null,
            "name": "Atman Entertainment",
            "origin_country": ""
        },
        {
            "id": 54052,
            "logo_path": null,
            "name": "Knickerbocker Films",
            "origin_country": "US"
        },
        {
            "id": 25,
            "logo_path": "/qZCc1lty5FzX30aOCVRBLzaVmcp.png",
            "name": "20th Century Fox",
            "origin_country": "US"
        },
        {
            "id": 4700,
            "logo_path": "/A32wmjrs9Psf4zw0uaixF0GXfxq.png",
            "name": "The Linson Company",
            "origin_country": ""
        }
    ],
    "production_countries": [
        {
            "iso_3166_1": "DE",
            "name": "Germany"
        },
        {
            "iso_3166_1": "US",
            "name": "United States of America"
        }
    ],
    "release_date": "1999-10-15",
    "revenue": 100853753,
    "runtime": 139,
    "spoken_languages": [
        {
            "iso_639_1": "en",
            "name": "English"
        }
    ],
    "status": "Released",
    "tagline": "Mischief. Mayhem. Soap.",
    "title": "Fight Club",
    "video": false,
    "vote_average": 8.4,
    "vote_count": 19690
}

このレスポンスはJSON objectになっているため、このレスポンスにdecode(_:from:)を呼ぶだけでは決して配列を結果として得ることはできません

そもそも、このレスポンス、(元のNSDictionary形式のままでも)中身をよくチェックすればわかりますが、映画1本分の情報しかありません。したがって「TableViewに...表示したい」と言う部分が意味を為しません。


あなたはこのTableViewに本当は何を表示したいのでしょうか?

TableViewの各行が映画1本を表示するようにしたい

⇒ 複数の映画情報を取得できるようなAPIを調べてそれを呼んでください。

TableViewが映画1本の中に複数存在する情報を1行ずつ表示するようにしたい

⇒ 一体自分は何の情報を表示したいのか調べてください。

映画1本分の情報を1つの画面に表示したい

⇒ TableViewを使わずに画面デザインをしてください


自分が呼び出しているAPIがどのような情報を返してくるのか、全く理解せずに使っておられるように見えます。学校か新人研修の課題なんでしょうか?

一体本来は何をしたいのかがもう少しわかれば、何か回答できる内容が増えるかもしれません。

Answered by OOPer on December 28, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP