Skip to content

Fix support for spring's HATEOAS data serialization transformations and provide FAQ example complex transformation #418

Closed
@skimbu

Description

@skimbu

Spring HATEOAS uses custom serializers for the couple of specific data types it uses, and springdoc doesn't know about these data types and thus maps them incorrectly to swagger.

Ideally there would be support for the automatic correct transformation of these data types in springdoc, otherwise, an example of how to use a PropertyCustomizer or similar to perform such mappings would be very helpful.

In particular:

The org.springframework.hateoas.RepresentationModel class represents a resource's links as a Collection<> named 'content' which needs to be translated in JSON to a field named '_embedded' of the same type.

The org.springframework.hateoas.CollectionModel class represents a resource's embedded contents as a List named 'links' which needs to be translated in JSON to a field named '_links' of type Map<String, Link>

I tried naively implementing a PropertyCustomizer to do this transformation but this didn't work, and there doesn't seem to be an example of a non-trivial PropertyCustomizer to base work from. Below is my failed attempt.

Ideally support for these types would be built-in to springdoc, otherwise a FAQ on how one might implement a suitable customizer would be even more flexible as it would allow others to implement other non-trivial transformations.

Lastly, many thanks for this project, it looks to be very high quality, excellent job!

@Component
public class OpenApiHateosFixup implements PropertyCustomizer {
    @Override
    public Schema customize(Schema property, AnnotatedType type) {

        // map from List<Link> to example Map<String,Link>
        if (property instanceof ArraySchema) {
            String typeRef = ((ArraySchema) property).getItems().get$ref();
            if (typeRef != null && typeRef.equals("#/components/schemas/Link")) {
                property = new MapSchema().type(typeRef); // seems to be ignored
            }
        }
        if (property != null) {
            // HATEOAS: map from 'links' field to '_links' and from "content" to "_embedded"
            if ("links".equals(type.getPropertyName())) {
                property.name("_links");  // seems to be ignored
            } else if ("content".equals(type.getPropertyName())) {
                property.name("_embedded");  // seems to be ignored
            }
        }
        return property;
    }

}

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions