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

Do not require JsonSubType annotation for sealed classes #2696

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* *
* * *
* * * *
* * * * * Copyright 2019-2022 the original author or authors.
* * * * * Copyright 2019-2024 the original author or authors.
* * * * *
* * * * * Licensed under the Apache License, Version 2.0 (the "License");
* * * * * you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -429,7 +429,7 @@ SpringDocProviders springDocProviders(Optional<ActuatorProvider> actuatorProvide
Optional<RepositoryRestResourceProvider> repositoryRestResourceProvider, Optional<RouterFunctionProvider> routerFunctionProvider,
Optional<SpringWebProvider> springWebProvider, Optional<WebConversionServiceProvider> webConversionServiceProvider,
ObjectMapperProvider objectMapperProvider) {
objectMapperProvider.jsonMapper().registerModule(new SpringDocRequiredModule());
objectMapperProvider.jsonMapper().registerModules(new SpringDocRequiredModule(), new SpringDocSealedClassModule());
return new SpringDocProviders(actuatorProvider, springCloudFunctionProvider, springSecurityOAuth2Provider, repositoryRestResourceProvider, routerFunctionProvider, springWebProvider, webConversionServiceProvider, objectMapperProvider);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
*
* *
* * *
* * * * Copyright 2024 the original author or authors.
* * * *
* * * * Licensed under the Apache License, Version 2.0 (the "License");
* * * * you may not use this file except in compliance with the License.
* * * * You may obtain a copy of the License at
* * * *
* * * * https://www.apache.org/licenses/LICENSE-2.0
* * * *
* * * * Unless required by applicable law or agreed to in writing, software
* * * * distributed under the License is distributed on an "AS IS" BASIS,
* * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * * * See the License for the specific language governing permissions and
* * * * limitations under the License.
* * *
* *
*
*/

package org.springdoc.core.configuration;

import com.fasterxml.jackson.databind.introspect.Annotated;
import com.fasterxml.jackson.databind.jsontype.NamedType;
import com.fasterxml.jackson.databind.module.SimpleModule;
import io.swagger.v3.core.jackson.SwaggerAnnotationIntrospector;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
* The type Spring doc sealed class module.
*
* @author sahil-ramagiri
*/
public class SpringDocSealedClassModule extends SimpleModule {

@Override
public void setupModule(SetupContext context) {
context.insertAnnotationIntrospector(new RespectSealedClassAnnotationIntrospector());
}

/**
* The type sealed class annotation introspector.
*/
private static class RespectSealedClassAnnotationIntrospector extends SwaggerAnnotationIntrospector {

@Override
public List<NamedType> findSubtypes(Annotated annotated) {
ArrayList<NamedType> subTypes = new ArrayList<>();

if (annotated.getAnnotated() instanceof Class<?> clazz && clazz.isSealed()) {
Class<?> permittedSubClasses = clazz.getPermittedSubclasses();
if (permittedSubClasses.length > 0) {
Arrays.stream(permittedSubClasses).map(NamedType::new).forEach(subTypes::add);
}
}

return subTypes;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
*
* *
* * *
* * * *
* * * * * Copyright 2019-2024 the original author or authors.
* * * * *
* * * * * Licensed under the Apache License, Version 2.0 (the "License");
* * * * * you may not use this file except in compliance with the License.
* * * * * You may obtain a copy of the License at
* * * * *
* * * * * https://www.apache.org/licenses/LICENSE-2.0
* * * * *
* * * * * Unless required by applicable law or agreed to in writing, software
* * * * * distributed under the License is distributed on an "AS IS" BASIS,
* * * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * * * * See the License for the specific language governing permissions and
* * * * * limitations under the License.
* * * *
* * *
* *
*
*/

package test.org.springdoc.api.v30.app224;


import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;

@JsonTypeInfo(use = Id.NAME, property = "type")
public abstract sealed class AbstractParent {
private int id;

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}
}

class final ChildOfAbstract1 extends AbstractParent {
private String abstrachChild1Param;

public String getAbstrachChild1Param() {
return abstrachChild1Param;
}

public void setAbstrachChild1Param(String abstrachChild1Param) {
this.abstrachChild1Param = abstrachChild1Param;
}
}

class final ChildOfAbstract2 extends AbstractParent {
private String abstractChild2Param;

public String getAbstractChild2Param() {
return abstractChild2Param;
}

public void setAbstractChild2Param(String abstractChild2Param) {
this.abstractChild2Param = abstractChild2Param;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
*
* *
* * *
* * * *
* * * * * Copyright 2019-2022 the original author or authors.
* * * * *
* * * * * Licensed under the Apache License, Version 2.0 (the "License");
* * * * * you may not use this file except in compliance with the License.
* * * * * You may obtain a copy of the License at
* * * * *
* * * * * https://www.apache.org/licenses/LICENSE-2.0
* * * * *
* * * * * Unless required by applicable law or agreed to in writing, software
* * * * * distributed under the License is distributed on an "AS IS" BASIS,
* * * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * * * * See the License for the specific language governing permissions and
* * * * * limitations under the License.
* * * *
* * *
* *
*
*/

package test.org.springdoc.api.v30.app224;


import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;

@JsonTypeInfo(use = Id.NAME, property = "type")
public sealed class ConcreteParent {
private int id;

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}
}

final class ChildOfConcrete1 extends ConcreteParent {
private String concreteChild1Param;

public String getConcreteChild1Param() {
return concreteChild1Param;
}

public void setConcreteChild1Param(String concreteChild1Param) {
this.concreteChild1Param = concreteChild1Param;
}
}

final class ChildOfConcrete2 extends ConcreteParent {
private String concreteChild2Param;

public String getConcreteChild2Param() {
return concreteChild2Param;
}

public void setConcreteChild2Param(String concreteChild2Param) {
this.concreteChild2Param = concreteChild2Param;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
*
* *
* * *
* * * *
* * * * * Copyright 2019-2022 the original author or authors.
* * * * *
* * * * * Licensed under the Apache License, Version 2.0 (the "License");
* * * * * you may not use this file except in compliance with the License.
* * * * * You may obtain a copy of the License at
* * * * *
* * * * * https://www.apache.org/licenses/LICENSE-2.0
* * * * *
* * * * * Unless required by applicable law or agreed to in writing, software
* * * * * distributed under the License is distributed on an "AS IS" BASIS,
* * * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * * * * See the License for the specific language governing permissions and
* * * * * limitations under the License.
* * * *
* * *
* *
*
*/

package test.org.springdoc.api.v30.app224;

import java.util.List;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("class-hierarchy")
public class Controller {
@PostMapping("abstract-parent")
public Response abstractParent(@RequestBody AbstractParent payload) {
return null;
}

@PostMapping("concrete-parent")
public Response concreteParent(@RequestBody ConcreteParent payload) {
return null;
}
}

class Response {
AbstractParent abstractParent;

List<ConcreteParent> concreteParents;

public AbstractParent getAbstractParent() {
return abstractParent;
}

public void setAbstractParent(AbstractParent abstractParent) {
this.abstractParent = abstractParent;
}

public List<ConcreteParent> getConcreteParents() {
return concreteParents;
}

public void setConcreteParents(List<ConcreteParent> concreteParents) {
this.concreteParents = concreteParents;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
*
* *
* * *
* * * *
* * * * * Copyright 2019-2024 the original author or authors.
* * * * *
* * * * * Licensed under the Apache License, Version 2.0 (the "License");
* * * * * you may not use this file except in compliance with the License.
* * * * * You may obtain a copy of the License at
* * * * *
* * * * * https://www.apache.org/licenses/LICENSE-2.0
* * * * *
* * * * * Unless required by applicable law or agreed to in writing, software
* * * * * distributed under the License is distributed on an "AS IS" BASIS,
* * * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * * * * See the License for the specific language governing permissions and
* * * * * limitations under the License.
* * * *
* * *
* *
*
*/

package test.org.springdoc.api.v30.app224;

import test.org.springdoc.api.v30.AbstractSpringDocV30Test;

import org.springframework.boot.autoconfigure.SpringBootApplication;


public class SpringDocApp224Test extends AbstractSpringDocV30Test {

@SpringBootApplication
static class SpringDocTestApp {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package test.org.springdoc.api.v30.app225;


import com.fasterxml.jackson.annotation.JsonTypeInfo;
import io.swagger.v3.oas.annotations.media.Schema;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

@PostMapping("/parent")
public void parentEndpoint(@RequestBody Superclass parent) {

}

}

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "@type")
sealed class Superclass permits IntermediateClass {

public Superclass() {}
}

@Schema(name = IntermediateClass.SCHEMA_NAME)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "@type")
sealed class IntermediateClass extends Superclass permits FirstChildClass, SecondChildClass {

public static final String SCHEMA_NAME = "IntermediateClass";
}

@Schema(name = FirstChildClass.SCHEMA_NAME)
final class FirstChildClass extends IntermediateClass {

public static final String SCHEMA_NAME = "Image";
}

@Schema(name = SecondChildClass.SCHEMA_NAME)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "@type")
sealed class SecondChildClass extends IntermediateClass {

public static final String SCHEMA_NAME = "Mail";
}

@Schema(name = ThirdChildClass.SCHEMA_NAME)
final class ThirdChildClass extends SecondChildClass {

public static final String SCHEMA_NAME = "Home";
}
Loading