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

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

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

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

API

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

Q&A

解決済

1回答

1376閲覧

[Swift]ネストしたJSONからデータを取得し表示したい

yasukun252

総合スコア34

Swift

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

API

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

0グッド

0クリップ

投稿2021/08/28 09:39

編集2021/08/28 10:25

前提・実現したいこと

http://127.0.0.1:3000のAPIから返ってきたネストしたJSONから値を取得して表示したい。

Swift初学者でして、ネストしたJSONを構造体に変換する部分や値の取得などがうまくいきません。

解決方法をお教えいただけますと幸いです。

http://127.0.0.1:3000/api/posts.jsonで以下のようなJSONがある場合、Swift側ではどのように構造体や変数を定義すれば良いでしょうか??

(APIの部分はRuby on Railsで実装しております。)

{ "posts": [ { "id": 1, "user_id": 1, "content": "テスト", "status": "public", "created_at": "2021-03-04T06:44:55.317+09:00", "updated_at": "2021-03-07T20:43:28.347+09:00", "photos": [ { "image": { "url": "/uploads/post_photo/image/1/2018-06-29_12.13.21.jpg", "thumb": { "url": "/uploads/post_photo/image/1/thumb_2018-06-29_12.13.21.jpg" } } } ] } ] }

現状は、以下のようにしております。

struct PostModel: Decodable { var posts: [Post] } struct Post: Decodable, Identifiable, Encodable { var photo: [Photo] var id: Int? var user_id: Int? var content: String var status: String var created_at: String var updated_at: String struct Photo: Decodable, Encodable { var image: [Image] struct Image: Decodable, Encodable { var url: String var thumb: [Thumb] struct Thumb: Decodable, Encodable { var url: String } } } }

APIの通信部分はAlamofireで実装しております。

class PostModelFetcher: ObservableObject { @Published var postData: [Post] = [] init() { fetchPostData() } func fetchPostData() { AF.request("http://127.0.0.1:3000/api/posts.json", method: .get, encoding: URLEncoding.default).response { response in guard let json = response.data else { return } let decoder: JSONDecoder = JSONDecoder() do { let searchedResultData = try decoder.decode(PostModel.self, from: json) DispatchQueue.main.async { self.postData = searchedResultData.posts.reversed() } } catch { print("json convert failed in JSONDecoder. " + error.localizedDescription) } debugPrint(response) } } }

リストのセルのViewは以下のように実装しております。(このViewに上記JSONのposts.photos.image.urlなどネストしたデータを表示したいです。)

struct PostRowView: View { var postData: Post var body: some View { VStack(alignment: .leading) { Text(postData.content) .bold() .font(.headline) .lineLimit(2) .padding(Edge.Set.top, 8.0) .padding(Edge.Set.bottom, 12.0) }  } } struct PostDetailView: View { var postData: Post var body: some View { Text("Hello, World!") } }

トップページのViewは以下のように実装しております。

struct ContentView: View { @ObservedObject var fetcher = PostModelFetcher() var body: some View { NavigationView { List(fetcher.postData) { post in NavigationLink(destination: PostDetailView(postData: post)) { PostRowView(postData: post) } } .navigationBarTitle(Text("投稿一覧")) } } }

API通信は以下のように出来ているのですが、json convert failed in JSONDecoder. The data couldn’t be read because it is missing.のエラーが発生しているため構造体の定義の方法などが間違っていると思い質問いたしました。

2021-08-28 18:12:55.048637+0900 RelatedModelApi[1356:1479807] [] nw_protocol_get_quic_image_block_invoke dlopen libquic failed json convert failed in JSONDecoder. The data couldn’t be read because it is missing. [Request]: GET http://127.0.0.1:3000/api/posts.json [Headers]: None [Body]: None [Response]: [Status Code]: 200 [Headers]: Cache-Control: max-age=0, private, must-revalidate Content-Type: application/json; charset=utf-8 Etag: W/"4cef57ad653583235e93452a6f553c45" Referrer-Policy: strict-origin-when-cross-origin Transfer-Encoding: Identity X-Content-Type-Options: nosniff X-Download-Options: noopen X-Frame-Options: SAMEORIGIN X-Permitted-Cross-Domain-Policies: none X-Rack-Dev-Mark-Env: development X-Request-Id: 34f6c77f-2925-42bc-bbfd-adbc11b66e35 X-Runtime: 0.104696 X-XSS-Protection: 1; mode=block [Body]: {"posts":[{"id":1,"user_id":1,"content":"テスト","status":"public","created_at":"2021-03-04T06:44:55.317+09:00","updated_at":"2021-03-07T20:43:28.347+09:00","photos":[{"image":{"url":"/uploads/post_photo/image/1/2018-06-29_12.13.21.jpg","thumb":{"url":"/uploads/post_photo/image/1/thumb_2018-06-29_12.13.21.jpg"}}}]}]} [Network Duration]: 0.955036997795105s [Serialization Duration]: 0.0s [Result]: success(Optional(495 bytes))

現状は、構造体の以下の部分を削除すればPost単体のデータは取得してセルに表示出来るという所までは分かっております。

var photo: [Photo] ... struct Photo: Decodable, Encodable { var image: [Image] struct Image: Decodable, Encodable { var url: String var thumb: [Thumb] struct Thumb: Decodable, Encodable { var url: String } } }

しかし、上記のPhotoとImageなども一緒にセルに表示したいです!!!

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

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

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

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

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

guest

回答1

0

ベストアンサー

とりあえずこれでいけるのでは。

  • photo じゃなくて photos ですね。
  • photos の中の image と、その中の thumb は配列ではありません。

diff

1 struct Post: Decodable, Identifiable, Encodable { 2- var photo: [Photo] 3+ var photos: [Photo] 4 5 var id: Int? 6 var user_id: Int? 7 var content: String 8 var status: String 9 var created_at: String 10 var updated_at: String 11 12 struct Photo: Decodable, Encodable { 13- var image: [Image] 14+ var image: Image 15 16 struct Image: Decodable, Encodable { 17 var url: String 18 19- var thumb: [Thumb] 20+ var thumb: Thumb 21 22 struct Thumb: Decodable, Encodable { 23 var url: String 24 } 25 } 26 } 27 }

投稿2021/08/28 12:12

編集2021/08/28 12:13
hoshi-takanori

総合スコア7895

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

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

yasukun252

2021/08/28 12:19

ご回答ありがとうございます!!! その場合は、vIewでの変数定義などはどのようにするべきでしょうか? Post単体ですと以下のようにアクセスできます。 struct PostRowView: View { var postData: Post var body: some View { VStack(alignment: .leading) { Text(postData.content) } これをPhotosやimageでも同じように表示したいです。
hoshi-takanori

2021/08/28 12:33

その postData を使って表示できると思いますが、問題はあなたがどう表示したいかですね。写真は複数あるので List とかでしょうか。 あと、JSON の中の URL がいわゆるルートパス (https://fastcoding.jp/blog/all/frontend/path/) になってるので、ホスト名を補ってダウンロードする必要がありますね。画像のダウンロードは SDWebImageSwiftUI あたりをお使いでしょうか?
yasukun252

2021/08/28 13:15

postData.photos.urlなどやっても駄目でした。 すみません、Swift初心者過ぎてよく分かりません...
hoshi-takanori

2021/08/28 13:30

postData.photos は配列なので、List とか ForEach とかする必要があります。 とりあえずこれで画像の URL が表示できるかと。あとは画像を読み込んで表示ですね…。 List(postData.photos, id: .image.url) { photo in Text("(photo.image.url)") }
yasukun252

2021/08/29 01:54

ありがとうございます‼︎ 画像のURLは表示されました‼︎ 画像の読み込みは頑張ってやってみます‼︎
yasukun252

2021/08/29 03:31 編集

すみません、最後に1つだけ教えて下さい... List(postData.photos, id: .image.url) { photo in WebImage(url: URL(string: "(photo.image.url)")) .resizable() .frame(width: 280, height: 200) .aspectRatio(contentMode: .fit) } SDWebImageSwiftUIを使って上記のようにすると、画像が読み込まれないのですが、 WebImage(url: URL(string: "https://www.~"))のようなPathにしなければならないのでしょうか? その場合は、ローカルの以下のような画像Pathでは表示できませんか? /uploads/post_photo/image/1/2018-06-29_12.13.21.jpg
yasukun252

2021/08/29 03:41

ありがとうございます!! やってみます。色々とありがとうございました!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問