Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Serialization to openapi of org.springframework.data.domain.Sort is not done correctly #2447

Closed
a-locatelli opened this issue Dec 5, 2023 · 4 comments
Labels
bug Something isn't working

Comments

@a-locatelli
Copy link

a-locatelli commented Dec 5, 2023

Hi,
There is something wrong with the serialization (to openapi) of the org.springframework.data.domain.Sort

I've a method which returns a org.springframework.data.domain.Page from a method in a RestController class.
The implementation of org.springframework.data.domain.Page is org.springframework.data.domain.PageImpl

@RestController
public class MyRestController {

  @PostMapping(path = "/", produces = APPLICATION_JSON_VALUE, consumes = APPLICATION_JSON_VALUE)
  @Operation(operationId="myOperation")
  public org.springframework.data.domain.Page<MyDto> queryMyDto(@RequestBody MyDtoQuery query, @ParameterObject org.springframework.data.domain.Pageable pageable) {
    // This return a PageImpl with the data, the method parameter 'query' is a pojo containg filter properties
    return myService.getResult(query, pageable); 
  }
}

The openapi defintion generated is:

"PageMyDto": {
  "type": "object",
  "properties": {
    "totalPages": {
      "type": "integer",
      "format": "int32"
    },
    "totalElements": {
      "type": "integer",
      "format": "int64"
    },
    "first": {
      "type": "boolean"
    },
    "last": {
      "type": "boolean"
    },
    "size": {
      "type": "integer",
      "format": "int32"
    },
    "content": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/MyDto"
      }
    },
    "number": {
      "type": "integer",
      "format": "int32"
    },
    "sort": {
      "$ref": "#/components/schemas/SortObject"
    },
    "numberOfElements": {
      "type": "integer",
      "format": "int32"
    },
    "pageable": {
      "$ref": "#/components/schemas/PageableObject"
    },
    "empty": {
      "type": "boolean"
    }
  }
},
"SortObject": {
  "type": "object",
  "properties": {
    "empty": {
      "type": "boolean"
    },
    "sorted": {
      "type": "boolean"
    },
    "unsorted": {
      "type": "boolean"
    }
  }
}

When i call the method, the return object is (content is empty for this example):

http://localhost:8180/?page=0&size=20

{
  "number": 0,
  "numberOfElements": 0,
  "totalElements": 0,
  "totalPages": 0,
  "size": 20,
  "sort": [],
  "content": []
}

As you can see, the "sort" property generated is not an array, and the SortObject does not contains the Sort properties like orders.

If i set the query parameter sort, the result is:

http://localhost:8180/?page=0&size=20&sort=id

{
  "number": 0,
  "numberOfElements": 0,
  "totalElements": 0,
  "totalPages": 0,
  "size": 20,
  "sort": [
    {
      "property": "id",
      "direction": "ASC",
      "ignoreCase": false,
      "nullHandling": "NATIVE"
    }
  ],
  "content": []
}

I'm using spring boot 3.1.6 and springdoc-openapi-webmvc-ui 2.3.0.

Can you help me figure out if there is a bug or if i'm doing something wrong?

Thanks

@a-locatelli a-locatelli changed the title Serialization of spring Sort is not done correctly Serialization to openapi of org.springframework.data.domain.Sort is not done correctly Dec 5, 2023
@Jodee90
Copy link

Jodee90 commented Dec 18, 2023

@a-locatelli Did you manage to solve this? Any workarounds?

@bnasslahsen
Copy link
Contributor

@a-locatelli,

I have added a fix for it.
Let me know if the fix works for you with the latest snapshot.

@bnasslahsen bnasslahsen added the bug Something isn't working label Feb 27, 2024
@SimoneFalzone
Copy link

I have the same problem, and your fix dosen't solved it.

Your excpected output is:

"sort": {
     "$ref": "#/components/schemas/SortObject"
},

But have to be:

"sort": {
  "type": "array",
  "items": {
    "$ref": "#/components/schemas/OrderObject"
  }
},

I implemented a workaround like this, with this the desired openapi.json is generated and from that working DTOs to use with Pageable and Sort.

@Configuration
class CustomOpenApiConfiguration {

    @Bean
    fun CustomSortSchemaConverter(): SortSchemaConverter {
        // Create and return the custom SortSchemaConverter
        return SortSchemaConverter()
    }
}

class SortSchemaConverter : ModelConverter {

    override fun resolve(
        type: AnnotatedType,
        context: ModelConverterContext,
        chain: MutableIterator<ModelConverter>
    ): Schema<*>? {
        val javaType = type.type

        return if (javaType is SimpleType && javaType.rawClass == Sort::class.java) {

            val orderSchema = ObjectSchema()
                .addProperty("direction", StringSchema())
                .addProperty("property", StringSchema())
                .addProperty("ignoreCase", BooleanSchema())
                .addProperty("nullHandling", StringSchema())
                .addProperty("ascending", BooleanSchema())
                .addProperty("descending", BooleanSchema())
            //  needs to be called whenever a Model is defined which can be referenced from another
            //  Model or Property
            context.defineModel("OrderObject", orderSchema)

            ArraySchema().items(
                Schema<Any>().`$ref`("#/components/schemas/OrderObject")
            )

        } else if (chain.hasNext()) {
            chain.next().resolve(type, context, chain)
        } else {
            null
        }
    }
}

@bnasslahsen
Copy link
Contributor

@SimoneFalzone,

Your proposed fix is too much lines of code, with too much assumptions that OrderObject schema exists.
There is much simpler way to do this.

bnasslahsen added a commit that referenced this issue Feb 28, 2024
@springdoc springdoc locked as resolved and limited conversation to collaborators Feb 28, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants