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

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

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

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

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

1回答

461閲覧

SwiftUIでRESTAPIからJSONを取得して描画したい2

shot110

総合スコア2

JSON

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

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2022/08/25 12:58

前提

SwiftUIでRESTAPIからJSONを取得して描画する練習コードを書いています。
階層構造のあるJSONの処理ができなくて困っています。
似たような質問を前回もしており申し訳ございませんが
SwiftUIに詳しい方ご協力よろしくお願いいたします。

利用中の開発環境
・MacBookPro macOS Monterey Apple M1 Pro
・Xcode 13.4.1

実現したいこと

SwiftUIでRESTAPIから以下のJSONを取得して、
"coordinate"と"SK"と"PK"の値をすべて画面に表示したい。

[ { "coordinate": { "S": "(0, 0)" }, "SK": { "S": "#TIMESTAMP#2022-08-24T09:42:33+09:00" }, "PK": { "S": "USER#test_uuid" } }, { "coordinate": { "S": "(35.6341, 139.7158)" }, "SK": { "S": "#TIMESTAMP#2022-08-24T07:25:32+09:00" }, "PK": { "S": "USER#test_uuid" } }, { "coordinate": { "S": "(35.6341, 139.7158)" }, "SK": { "S": "#TIMESTAMP#2022-08-24T06:25:32+09:00" }, "PK": { "S": "USER#test_uuid" } }, { "coordinate": { "S": "(35.6341, 139.7158)" }, "SK": { "S": "#TIMESTAMP#2022-08-24T03:25:32+09:00" }, "PK": { "S": "USER#test_uuid" } }, { "coordinate": { "S": "(35.6341, 139.7158)" }, "SK": { "S": "#TIMESTAMP#2022-08-23T03:25:32+09:00" }, "PK": { "S": "USER#test_uuid" } }, { "coordinate": { "S": "(35.6341, 139.7158)" }, "SK": { "S": "#TIMESTAMP#2020-02-14T13:25:32+09:00" }, "PK": { "S": "USER#test_uuid" } } ]

発生している問題・エラーメッセージ

エラーが出ていないので、デコードがうまく行っていないのか
描画の記述がよくないのか検討つきませんでした。

該当のソースコード

swift

1import SwiftUI 2 3struct Items: Codable { 4 var coordinate:Coordinate? 5 var SK: sk? 6 var PK: pk? 7} 8 9struct Coordinate : Codable{ 10 var S: String? 11} 12 13struct sk : Codable{ 14 var S: String? 15} 16 17struct pk : Codable{ 18 var S: String? 19} 20 21 22struct TestRestApi2: View { 23 24 @State private var results: Items? 25 26 var body: some View { 27 NavigationView { 28 VStack{ 29 Text(results?.coordinate?.S ?? "") 30 Text(results?.SK?.S ?? "") 31 Text(results?.PK?.S ?? "") 32 } 33 }.onAppear(perform: loadData) // データ読み込み処理 34 } 35 /// データ読み込み処理 36 func loadData() { 37 38 /// URLの生成 39 guard let url = URL(string: 40 "https://dvbd52dkle.execute-api.ap-northeast-1.amazonaws.com/api/v0/timestamps") else { 41 /// 文字列が有効なURLでない場合の処理 42 return 43 } 44 45 /// URLリクエストの生成 46 var request = URLRequest(url: url) 47 48 // POSTを指定 49 request.httpMethod = "POST" 50 51 // content-type を application/json に設定する 52 request.addValue("application/json", forHTTPHeaderField: "content-type") 53 54 // set the request-body(JSON) POSTのテストでポストしているだけ 55 let params: [String: Any] = [ 56 "testNumber": "123567", 57 ] 58 59 do{ 60 request.httpBody = try JSONSerialization.data(withJSONObject: params, options: []) 61 }catch{ 62 print("エラー1") 63 print(error.localizedDescription) 64 } 65 66 /// URLにアクセス 67 URLSession.shared.dataTask(with: request) { data, response, error in 68 69 do { 70 if let items = data { 71 let decodedData = try JSONDecoder().decode(Items.self, from: items) 72 self.results = decodedData 73 print("出力") 74 print(decodedData.coordinate?.S) 75 } else { 76 print("No data", data as Any) 77 } 78 } catch { 79 print("エラー2") 80 print("Error", error) 81 } 82 83 }.resume() // タスク開始処理(必須) 84 85 } 86} 87 88struct TestRestApi2_Previews: PreviewProvider { 89 static var previews: some View { 90 TestRestApi2() 91 } 92} 93 94 95

試したこと

VStack{ Text(results?.coordinate?.S ?? "") Text(results?.SK?.S ?? "") Text(results?.PK?.S ?? "") }

これだと配列の中のすべての値を描画するには、書き方が違っているっぽいなとしかわかりませんでした。

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

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

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

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

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

guest

回答1

0

ベストアンサー

再現確認してみたところ「エラー2」が出力されているようでした。

JSONの一番外側は配列([])のようですので、JSONDecoderを使うときもItemsの配列にしてあげると良いと思います。

swift

1// ***** Itemsの配列です 2@State private var results: [Items]? 3 4// ***** Itemsの配列です 5let decodedData = try JSONDecoder().decode([Items].self, from: items)

これだと配列の中のすべての値を描画するには、書き方が違っているっぽいなとしかわかりませんでした。

こちらはSwiftUIのチュートリアルを実践してみると良いと思います。

https://developer.apple.com/tutorials/swiftui/building-lists-and-navigation

追記です。

コメントありがとうございます。

Itemsを配列で用意すると以下のエラーがでてしまいました。
JSONの中身が配列のような気もするのですが、、

ごめんなさい。
他人のAPIを勝手にテストで使わない方が良いかなと思いまして、
質問欄のJSONをローカルのWebサーバーに置いて確認していました・・

レスポンスが500エラーになっているみたいですね。
次のようにコードを修正してエラーを確認してみてください。
エラー処理なども検討した方が良いかもしれませんね。

swift

1/// URLにアクセス 2URLSession.shared.dataTask(with: request) { data, response, error in 3 if let e = error { 4 print(e) 5 } 6 if let r = response, 7 let h = r as? HTTPURLResponse { 8 print(h.statusCode) 9 } 10 if let d = data, 11 let s = String(data: d, encoding: .utf8) { 12 print(s) 13 } 14 // ...省略...

printの内容は次のような感じになりました。
*HTTPステータスコードが500で、dataはエラーメッセージになっているようでした。

500 {"message":"Internal Server Error"}

レスポンスのエラーが解消されて、質問欄のJSONが返ってくるようになれば、最初の回答の通りで大丈夫だと思うのですが、いかがでしょうか。

投稿2022/08/25 14:16

編集2022/08/26 02:35
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

shot110

2022/08/26 02:03

ご回答ありがとうございます! SwiftUIのチュートリアル情報ありがとうございます。 Itemsを配列で用意すると以下のエラーがでてしまいました。 JSONの中身が配列のような気もするのですが、、 エラー2 Error typeMismatch(Swift.Array<Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Array<Any> but found a dictionary instead.", underlyingError: nil))
shot110

2022/08/26 05:22

追記ありがとうございます。 申し訳ございません。APIにGETで投げるところPOSTで投げていたことで500エラー出ていました、、 URLアクセスのエラー処理も勉強になりました。 ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問