Swiftgger icon indicating copy to clipboard operation
Swiftgger copied to clipboard

Issue with nested array of encodable objects

Open AndriyVasyk opened this issue 3 years ago • 4 comments

Hello! Could you please to take a look at the following issue: I have found that a collection of encodable objects is missing under Example Values. See image below: Screenshot 2021-06-17 at 09 33 45

And here is a code snippet to reproduce the issue:

struct NestedObject: Encodable {
    var version: String
    var value: String
}

struct TestObject: Encodable {
    var nested: NestedObject
    var nestedObjects: [NestedObject]
    var nestedValues: [String]
}

        let nested1 = NestedObject(version: "1.0", value: "Nested Object 1")
        let nested2 = NestedObject(version: "2.0", value: "Nested Object 2")
        let nested3 = NestedObject(version: "3.0", value: "Nested Object 3")
        let test = TestObject(nested:nested1, nestedObjects: [nested2, nested3],
                              nestedValues: ["Str1", "Str2"])
        
        let openAPIBuilder = OpenAPIBuilder(
            title: "Tasker server API",
            version: "1.0.0",
            description: "This is a sample server for task server application."
        )
        .add([
            APIObject(object: test)
        ])
        .add(APIController(name: "Test",
                           description: "Controller where we can manage test",
                           actions: [
                                APIAction(method: .get,
                                          route: "/test",
                                          summary: "Summary",
                                          description: "Description",
                                          responses: [
                                            APIResponse(code: "200",
                                                        description: "Ok",
                                                        type: .object(TestObject.self))
                                          ],
                                          authorization: false)
                           ])
        )

        let openAPIDocument = openAPIBuilder.built()

        let encoder = JSONEncoder()
        encoder.outputFormatting = .prettyPrinted

        let jsonData = try! encoder.encode(openAPIDocument)
        let jsonString = String(bytes: jsonData, encoding: .utf8)
        print(jsonString!)
        return jsonString!

AndriyVasyk avatar Jun 17 '21 06:06 AndriyVasyk

You have to register all objects. In your case NestedObject and TestObject.

let nested1 = NestedObject(version: "1.0", value: "Nested Object 1")
let test = TestObject(nested:nested1, nestedObjects: [nested1], nestedValues: ["Str1", "Str2"])

let openAPIBuilder = OpenAPIBuilder(
    title: "Tasker server API",
    version: "1.0.0",
    description: "This is a sample server for task server application."
)
.add([
    APIObject(object: test),
    APIObject(object: nested1)     // <- add also nested
])

Nested objects in OpenAPI definition are added as a reference (name of the type, not real objects).

mczachurski avatar Jun 18 '21 15:06 mczachurski

I tried to register NestedObject as you suggested. But it still does not contain NestedObject. Here is the code I tried:

            let nested = NestedObject(version: "1.0", value: "Nested Object 1")
            let test = TestObject(nestedObjects: [nested])

            let openAPIBuilder = OpenAPIBuilder(
                title: "Tasker server API",
                version: "1.0.0",
                description: "This is a sample server for task server application."
            )
            .add([
                APIObject(object: test),
                APIObject(object: nested)
            ])
            .add(APIController(name: "Test",
                               description: "Controller where we can manage test",
                               actions: [
                                    APIAction(method: .get,
                                              route: "/test",
                                              summary: "Summary",
                                              description: "Description",
                                              responses: [
                                                APIResponse(code: "200",
                                                            description: "Ok",
                                                            type: .object(TestObject.self))
                                              ],
                                              authorization: false)
                               ])
            )

            let openAPIDocument = openAPIBuilder.built()

            let encoder = JSONEncoder()
            encoder.outputFormatting = .prettyPrinted

            let jsonData = try! encoder.encode(openAPIDocument)
            let jsonString = String(bytes: jsonData, encoding: .utf8)

JSON: json.txt

Screenshot: Screenshot 2021-06-24 at 09 22 14

AndriyVasyk avatar Jun 24 '21 06:06 AndriyVasyk

I've copy&paste your code and I've different result.

image

Are you sure that you are using latest Swiftgger version (2.0.0-rc1)?

mczachurski avatar Jun 25 '21 14:06 mczachurski

Yeah, I updated Swiftgger and now it works in most cases. However i am seeing the same issue with array of nested optional objects ( [NestedObject?] ). Could you please to take a look the issue with the following code? And confirm whether this works. Or maybe I am doing something wrong again?

struct NestedObject: Content {
    var value: String
}
struct TestObject: Content {
    var nestedObjects: [NestedObject?] // --> This line is changed in comparison to previous examples
}
        let nested = NestedObject(value: "Nested Object 1")
        let test = TestObject(nestedObjects: [nested])

        let openAPIBuilder = OpenAPIBuilder(
            title: "Tasker server API",
            version: "1.0.0",
            description: "This is a sample server for task server application."
        )
        .add([
            APIObject(object: nested),
            APIObject(object: test)
        ])
        .add(APIController(name: "Test",
                           description: "Controller where we can manage test",
                           actions: [
                                APIAction(method: .get,
                                          route: "/test",
                                          summary: "Summary",
                                          description: "Description",
                                          responses: [
                                            APIResponse(code: "200",
                                                        description: "Ok",
                                                        type: .object(TestObject.self))
                                          ],
                                          authorization: false)
                           ])
        )

        let openAPIDocument = openAPIBuilder.built()
        let data = try JSONEncoder().encode(openAPIDocument)
        let serializedData = String(data: data, encoding: .utf8)!
        return serializedData

AndriyVasyk avatar Jul 30 '21 12:07 AndriyVasyk