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

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

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

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

Swift

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

Q&A

解決済

2回答

497閲覧

JSONの読み込み(swift)

denshatrain

総合スコア16

JSON

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

Swift

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

0グッド

1クリップ

投稿2018/09/11 20:58

編集2018/09/12 21:04

前提・実現したいこと

swiftで下のようなJSONを読み込みたいです。
読み込みたい場所はvideoIDtitleです

json

1{ 2 "kind": "youtube#searchListResponse", 3 "etag": "\"XI7nbFXulYBIpL0ayR_gDh3eu1k/sK9J7bsFpx18009cMMg0Lm6BSUg\"", 4 "nextPageToken": "CAoQAA", 5 "regionCode": "JP", 6 "pageInfo": { 7 "totalResults": 7161, 8 "resultsPerPage": 10 9 }, 10 "items": [ 11 { 12 "kind": "youtube#searchResult", 13 "etag": "\"XI7nbFXulYBIpL0ayR_gDh3eu1k/n8MR9oEibzEjQGRvkJ2YD_uMgIo\"", 14 "id": { 15 "kind": "youtube#video", 16 "videoId": "pCQ8LDrTXbE" 17 }, 18 "snippet": { 19 "publishedAt": "2016-08-12T09:30:01.000Z", 20 "channelId": "UCEzPCE4ULESqrp2m013wrlA", 21 "title": "【Minecraft】うるさいけどロマンなエスカレーター【へぼてっく】", 22 "description": "へぼてっくが、ヘボいテクでマインクラフトを楽しみます。 暇つぶし程度に見てください(笑) 万が一、役に立てることがあったら嬉しいのだけど...", 23 "thumbnails": { 24 "default": { 25 "url": "https://i.ytimg.com/vi/pCQ8LDrTXbE/default.jpg", 26 "width": 120, 27 "height": 90 28 }, 29 "medium": { 30 "url": "https://i.ytimg.com/vi/pCQ8LDrTXbE/mqdefault.jpg", 31 "width": 320, 32 "height": 180 33 }, 34 "high": { 35 "url": "https://i.ytimg.com/vi/pCQ8LDrTXbE/hqdefault.jpg", 36 "width": 480, 37 "height": 360 38 } 39 }, 40 "channelTitle": "へぼてっくちゃんねる", 41 "liveBroadcastContent": "none" 42 } 43 }, 44 { 45 "kind": "youtube#searchResult", 46 "etag": "\"XI7nbFXulYBIpL0ayR_gDh3eu1k/Q_XYdMQnRI09uy066b4JDGYJHX4\"", 47 "id": { 48 "kind": "youtube#video", 49 "videoId": "3gaRTWP8jwI" 50 }, 51 "snippet": { 52 "publishedAt": "2015-02-06T09:00:16.000Z", 53 "channelId": "UCEzPCE4ULESqrp2m013wrlA", 54 "title": "【Minecraft】完全水抜き海底神殿で迷うw【へぼてっく】", 55 "description": "へぼてっくが、ヘボいテクでマインクラフトを楽しみます。 暇つぶし程度に見てください(笑) 万が一、役に立てることがあったら嬉しいのだけど...", 56 "thumbnails": { 57 "default": { 58 "url": "https://i.ytimg.com/vi/3gaRTWP8jwI/default.jpg", 59 "width": 120, 60 "height": 90 61 }, 62 "medium": { 63 "url": "https://i.ytimg.com/vi/3gaRTWP8jwI/mqdefault.jpg", 64 "width": 320, 65 "height": 180 66 }, 67 "high": { 68 "url": "https://i.ytimg.com/vi/3gaRTWP8jwI/hqdefault.jpg", 69 "width": 480, 70 "height": 360 71 } 72 }, 73 "channelTitle": "へぼてっくちゃんねる", 74 "liveBroadcastContent": "none" 75 } 76 }, 77 { 78 "kind": "youtube#searchResult", 79 "etag": "\"XI7nbFXulYBIpL0ayR_gDh3eu1k/J3jkHc1QCoTbjo5VVrt58e7rIy0\"", 80 "id": { 81 "kind": "youtube#video", 82 "videoId": "lYU4Hmnov00" 83 }, 84 "snippet": { 85 "publishedAt": "2016-05-20T09:30:00.000Z", 86 "channelId": "UCEzPCE4ULESqrp2m013wrlA", 87 "title": "【Minecraft】Gホイホイ的なエンダーマントラップタワー【へぼてっく】", 88 "description": "へぼてっくが、ヘボいテクでマインクラフトを楽しみます。 暇つぶし程度に見てください(笑) 万が一、役に立てることがあったら嬉しいのだけど...", 89 "thumbnails": { 90 "default": { 91 "url": "https://i.ytimg.com/vi/lYU4Hmnov00/default.jpg", 92 "width": 120, 93 "height": 90 94 }, 95 "medium": { 96 "url": "https://i.ytimg.com/vi/lYU4Hmnov00/mqdefault.jpg", 97 "width": 320, 98 "height": 180 99 }, 100 "high": { 101 "url": "https://i.ytimg.com/vi/lYU4Hmnov00/hqdefault.jpg", 102 "width": 480, 103 "height": 360 104 } 105 }, 106 "channelTitle": "へぼてっくちゃんねる", 107 "liveBroadcastContent": "none" 108 } 109 } 110 ] 111} 112

###今のコード

swift

1class ItemSearchResultSet: Codable { 2 var items: Items 3 4 private enum CodingKeys: String, CodingKey { 5 case items = "items" 6 } 7} 8 9class Items: Codable { 10 var id: Id 11 var snippet: Snippet 12 13 private enum CodingKeys: String, CodingKey { 14 case id = "id" 15 case snippet = "snippet" 16 } 17} 18 19class Snippet: Codable { 20 var title: Title 21 22 private enum CodingKeys: String, CodingKey { 23 case title = "title" 24 } 25} 26 27class Id: Codable { 28 var items: [ItemData] = [ItemData]() 29 required init(from decoder: Decoder) throws { 30 let container = try decoder.container(keyedBy: CodingKeys.self) 31 let keys = container.allKeys.sorted { 32 Int($0.rawValue)! < Int($1.rawValue)! 33 } 34 for key in keys { 35 let item = try container.decode(ItemData.self, forKey: key) 36 items.append(item) 37 } 38 } 39 40 func encode(to encoder: Encoder) throws { 41 } 42 43 private enum CodingKeys: String, CodingKey { 44 case hit0 = "0" 45 case hit1 = "1" 46 case hit2 = "2" 47 case hit3 = "3" 48 case hit4 = "4" 49 case hit5 = "5" 50 case hit6 = "6" 51 case hit7 = "7" 52 case hit8 = "8" 53 case hit9 = "9" 54 case hit10 = "10" 55 case hit11 = "11" 56 case hit12 = "12" 57 case hit13 = "13" 58 case hit14 = "14" 59 case hit15 = "15" 60 case hit16 = "16" 61 case hit17 = "17" 62 case hit18 = "18" 63 case hit19 = "19" 64 case hit20 = "20" 65 } 66 67} 68 69class Title: Codable { 70 var items: [ItemData] = [ItemData]() 71 required init(from decoder: Decoder) throws { 72 let container = try decoder.container(keyedBy: CodingKeys.self) 73 let keys = container.allKeys.sorted { 74 Int($0.rawValue)! < Int($1.rawValue)! 75 } 76 for key in keys { 77 let item = try container.decode(ItemData.self, forKey: key) 78 items.append(item) 79 } 80 } 81 82 func encode(to encoder: Encoder) throws { 83 } 84 85 private enum CodingKeys: String, CodingKey { 86 case hit0 = "0" 87 case hit1 = "1" 88 case hit2 = "2" 89 case hit3 = "3" 90 case hit4 = "4" 91 case hit5 = "5" 92 case hit6 = "6" 93 case hit7 = "7" 94 case hit8 = "8" 95 case hit9 = "9" 96 case hit10 = "10" 97 case hit11 = "11" 98 case hit12 = "12" 99 case hit13 = "13" 100 case hit14 = "14" 101 case hit15 = "15" 102 case hit16 = "16" 103 case hit17 = "17" 104 case hit18 = "18" 105 case hit19 = "19" 106 case hit20 = "20" 107 } 108 109} 110 111class ItemData: Codable { 112 var title: String = "" 113 var videoId: String = "" 114 115 private enum CodingKeys: String, CodingKey { 116// case title = "title" 117 case videoId = "videoId" 118 } 119 120} 121 122 123 124class ViewController: UIViewController , UISearchBarDelegate { 125 126 @IBOutlet var searchBar: UISearchBar! 127 128 var itemDataArray = [ItemData]() 129 130 let appid = "AIzaSyCAIznRo4MUdgBtijMnd2De9YEUqMdmwaY" 131 132 let entryUrl: String = "https://www.googleapis.com/youtube/v3/search?key=AIzaSyCAIznRo4MUdgBtijMnd2De9YEUqMdmwaY&q=" 133 134 override func viewDidLoad() { 135 super.viewDidLoad() 136 // Do any additional setup after loading the view, typically from a nib. 137 138 searchBar.placeholder = "ここに入力してください" 139 searchBar.delegate = self 140 } 141 142 override func didReceiveMemoryWarning() { 143 super.didReceiveMemoryWarning() 144 // Dispose of any resources that can be recreated. 145 } 146 147 func searchBarSearchButtonClicked(_ searchBar: UISearchBar) { 148 149 print("検索ボタンがタップされました!") 150 151 guard let inputText = searchBar.text else { 152 return 153 } 154 155 guard inputText.lengthOfBytes(using: String.Encoding.utf8) > 0 else { 156 return 157 } 158 159 itemDataArray.removeAll() 160 161 let parameter = ["appid": appid, "query": inputText] 162 163 guard let escapedInputText = inputText.addingPercentEncoding( 164 withAllowedCharacters: CharacterSet.urlQueryAllowed 165 ) else { 166 return 167 } 168 let requestUrl = entryUrl + escapedInputText + "&part=snippet&maxResults=10&order=viewCount" 169 170 171 request(requestUrl: requestUrl) 172 173 searchBar.resignFirstResponder() 174 print(itemDataArray) 175 } 176 177 func request(requestUrl: String) { 178 print(1) 179 180 guard let url = URL(string: requestUrl) else { 181 return 182 } 183 184 let request = URLRequest(url: url) 185 let session = URLSession.shared 186 let task = session.dataTask (with: request) { (data:Data?, response:URLResponse?, error:Error?) in 187 guard error == nil else { 188 let alert = UIAlertController(title: "エラー", message: error?.localizedDescription, preferredStyle: .alert) 189 DispatchQueue.main.async { 190 self.present(alert, animated: true, completion: nil) 191 } 192 return 193 } 194 195 guard let data = data else { 196 return 197 } 198 199 do { 200 let resultSet = try JSONDecoder().decode(ItemSearchResultSet.self, from: data) 201 202 self.itemDataArray.append(contentsOf: resultSet.items.id.items) 203// self.itemDataArray.append(contentsOf: resultSet.items.snippet.title.items) 204 print("データーが追加されました") 205 print(self.itemDataArray) 206 } catch let error { 207 print("## error: (error)") 208 } 209 DispatchQueue.main.async { 210// self.tableView.reloadData() 211 } 212 } 213 print(2) 214 task.resume() 215 } 216}

###エラー

コンソールに

## error: keyNotFound(CodingKeys(stringValue: "items", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: \"items\", intValue: nil) (\"items\").", underlyingError: nil))

と表示されています。

###困っている点

ネットを見たり本を見たりしながらやっているのですがうまく読み込んでくれません。

補足情報

swift4.1
ios11.4

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

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

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

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

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

fuzzball

2018/09/12 00:06

コードを書いて下さい。
guest

回答2

0

ベストアンサー

SwiftyJSONを利用しましょう。
https://github.com/SwiftyJSON/SwiftyJSON
サンプルプロジェクトをベース適応させてみてください。

投稿2018/09/15 09:44

Leader731

総合スコア20

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

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

0

間違い探し

swift

1class ItemSearchResultSet: Codable { 2 var items: [Items] //配列です 3 : 4} 5 6class Snippet: Codable { 7 var title: String //ただの文字列です 8 : 9}

投稿2018/09/13 01:26

fuzzball

総合スコア16731

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

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

denshatrain

2018/09/13 20:58

`ItemSearchResultSet`のところを`[item]`に変えたのですが今度は `Extraneous argument label 'contentsOf:' in call Replace 'contentsOf: ' with ''` というエラーが出ます。それを直すと今度は `Value of type '[Items]' has no member 'snippet'`というエラーが出ます。 どうしたら良いでしょうか。
fuzzball

2018/09/13 22:39

修正点は正しく書いて下さい。(修正箇所だけここにコピペして下さい) titleの型は修正していないのでしょうか?
denshatrain

2018/09/15 23:28

titleの方も変更しましたが同様のエラーが出ています。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問