Closed JPM-Tech closed 2 months ago
Hey @JPM-Tech, thanks for reaching out.
There are at least two problems here:
Your OpenAPI document for the getPosts operation doesn't return an array, but a single JSON object. You'll need to specify in the OpenAPI document that this returns an array.
You'll need to either use the generated type (Components.Schemas.Post
) as your array element type or otherwise provide a mapping to the manually defined Post
type you created. The latter shouldn't be necessary as the whole point of generating these types is that you don't have to handwrite them.
That gives me a direction to go. Thank you @simonjbeaumont for your help! Would you mind sharing an example of what the suggested code might look like, and how it might be used in the view code above?
@JPM-Tech I’ll take a look at this tomorrow, sure.
That would be awesome! If it helps, this is a sample of the JSON that I am getting back from the service:
[
{
"userId": 1,
"id": 1,
"title": "sunt aut facere",
"body": "quia et suscipit\n"
},
{
"userId": 1,
"id": 2,
"title": "qui est esse",
"body": "est rerum tempore\n"
}
]
I was able to continue working and came up with a working solution. For anyone else who comes across this in the future. My openapi.yaml was slightly off, here is the corrected version:
openapi: "3.0.3"
info:
title: "PostService"
version: "1.0.0"
servers:
- url: "https://jsonplaceholder.typicode.com"
description: "An endpoint to get various objects"
paths:
/posts:
get:
operationId: "getPosts"
responses:
"200":
description: "Returns an array of post objects"
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/Post"
components:
schemas:
Post:
type: object
required:
- userId
- id
- title
- body
properties:
userId:
type: integer
example: 1
id:
type: integer
example: 1
title:
type: string
example: "title ipsum"
body:
type: string
example: "body ipsum"
The view code now looks like the following:
@State var postData = [Components.Schemas.Post]()
func getData() async throws {
let response = try await client.getPosts(Operations.getPosts.Input())
switch response {
case .ok(let okResponse):
switch okResponse.body {
case .json(let postResponse):
postData = postResponse
}
case .undocumented(statusCode: let statusCode, _):
print("Undocumented Error: \(statusCode)")
}
}
var body: some View {
VStack {
List(postData, id: \.id) { post in
Text(post.title)
}
Button("Get Data") {
Task {
try? await getData()
}
}
}
}
That looks good @JPM-Tech - anything else we can help with? Otherwise, please close this issue 🙂
@JPM-Tech that looks exactly what I meant by both (1) and (2) in my above message. Glad you got it working.
There's an additional shorthand you can use if you don't want to switch over all the responses and content types, for which there are only one of each here. It's less defensive, but if you're only interested in the outcome you expect and otherwise are happy to swallow the error, you can use the following:
@State var postData = [Components.Schemas.Post]()
func getData() async throws {
- let response = try await client.getPosts(Operations.getPosts.Input())
-
- switch response {
- case .ok(let okResponse):
- switch okResponse.body {
- case .json(let postResponse):
- postData = postResponse
- }
- case .undocumented(statusCode: let statusCode, _):
- print("Undocumented Error: \(statusCode)")
- }
+ postData = try await client.getPosts().ok.json
+ // ^ ^
+ // | ` .ok and .json are throwing computed properties.
+ // `- No request arguments, so no need to provide input.
}
Awesome work! Thank you!
Question
I am trying to convert the response into an array of swift objects, but I'm having a hard time figuring out how this should work?
Below is my example code:
When trying to assign the postResponse to the postData object gives the following error: Cannot assign value of type 'Components.Schemas.Post' to type '[Post]'
There aren't any examples that I could find of how to set an example list this up, and maybe there is something wrong with my openapi.yaml file (it was manually created since I don't own the service I am testing this API with)
Any help on how to do this the right way would be greatly appreciated