diff --git a/pom.xml b/pom.xml
index 11d2d4aa..41dda689 100644
--- a/pom.xml
+++ b/pom.xml
@@ -38,7 +38,7 @@
3.26.1
5.10.3
5.12.0
- 2.2.22
+ 2.2.36
4.0.3
2.17.1
0.0.3
@@ -349,7 +349,7 @@
io.swagger.core.v3
- swagger-annotations
+ swagger-annotations-jakarta
${swagger.version}
diff --git a/unknow-server-maven/pom.xml b/unknow-server-maven/pom.xml
index 20f6f9f9..82443e93 100644
--- a/unknow-server-maven/pom.xml
+++ b/unknow-server-maven/pom.xml
@@ -129,7 +129,7 @@
io.swagger.core.v3
- swagger-annotations
+ swagger-annotations-jakarta
io.swagger.core.v3
diff --git a/unknow-server-maven/src/main/java/unknow/server/maven/jaxrs/OpenApiBuilder.java b/unknow-server-maven/src/main/java/unknow/server/maven/jaxrs/OpenApiBuilder.java
index a456c581..b0f70603 100644
--- a/unknow-server-maven/src/main/java/unknow/server/maven/jaxrs/OpenApiBuilder.java
+++ b/unknow-server-maven/src/main/java/unknow/server/maven/jaxrs/OpenApiBuilder.java
@@ -15,6 +15,8 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
import java.util.stream.Collectors;
import org.apache.maven.plugin.MojoExecutionException;
@@ -22,8 +24,13 @@
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
+import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
import io.swagger.v3.oas.annotations.tags.Tags;
import io.swagger.v3.oas.models.OpenAPI;
@@ -41,6 +48,7 @@
import unknow.server.maven.jaxrs.JaxrsParam.JaxrsBeanParam.JaxrsBeanFieldParam;
import unknow.server.maven.jaxrs.JaxrsParam.JaxrsBodyParam;
import unknow.server.maven.jaxrs.JaxrsParam.JaxrsCookieParam;
+import unknow.server.maven.jaxrs.JaxrsParam.JaxrsFormParam;
import unknow.server.maven.jaxrs.JaxrsParam.JaxrsHeaderParam;
import unknow.server.maven.jaxrs.JaxrsParam.JaxrsMatrixParam;
import unknow.server.maven.jaxrs.JaxrsParam.JaxrsPathParam;
@@ -134,9 +142,10 @@ private static Schema> getDefault(String n) {
private final Map schemas = new HashMap<>();
public void build(OpenAPI spec, JaxrsModel model, String file) throws MojoExecutionException {
+ SimpleModule module = new SimpleModule().setSerializerModifier(new IgnoreOpenapiField());
ObjectMapper m = new ObjectMapper().enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING).disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
- .setDefaultPropertyInclusion(Include.NON_EMPTY);
+ .setDefaultPropertyInclusion(Include.NON_EMPTY).registerModule(module);
Path path = java.nio.file.Paths.get(file);
try {
Files.createDirectories(path.getParent());
@@ -172,9 +181,6 @@ private OpenAPI build(OpenAPI spec, JaxrsModel model) {
o.setTags(tags);
}
- ApiResponses responses = new ApiResponses();
- o.setResponses(responses);
-
if (a != null) {
a.member("tags").filter(v -> v.isSet()).map(v -> v.asArrayLiteral()).filter(v -> v.length > 0).ifPresent(v -> o.setTags(Arrays.asList(v)));
a.member("summary").filter(v -> v.isSet()).map(v -> v.asLiteral()).filter(v -> !v.isEmpty()).ifPresent(v -> o.setSummary(v));
@@ -187,12 +193,13 @@ private OpenAPI build(OpenAPI spec, JaxrsModel model) {
// TODO externalDocs, responses, security, servers, extensions
}
- if (responses.isEmpty() && !m.m.type().isVoid()) {
+ if (!m.m.type().isVoid()) {
Content c = new Content();
for (String s : m.produce)
c.addMediaType(s, new MediaType().schema(schema(m.m.type())));
- responses.addApiResponse("default", new ApiResponse().content(c));
- }
+ o.setResponses(new ApiResponses().addApiResponse("default", new ApiResponse().description("default").content(c)));
+ } else
+ o.setResponses(new ApiResponses().addApiResponse("default", new ApiResponse().description("empty")));
for (JaxrsParam> param : m.params)
addParameters(o, param);
@@ -215,16 +222,24 @@ private void addParameters(Operation o, JaxrsParam> param) {
}
if (param instanceof JaxrsBodyParam) {
- MediaType mdi = new MediaType();
- mdi.examples(null);
- mdi.schema(schema(param.type));
+ MediaType mdi = new MediaType().schema(schema(param.type));
Content content = new Content();
content.addMediaType("*/*", mdi);
o.setRequestBody(new RequestBody().content(content));
return;
}
- Parameter p = new Parameter().name(param.value).schema(schema(param.type));
+ Optional annotation = param.p.annotation(io.swagger.v3.oas.annotations.media.Schema.class);
+ if (param instanceof JaxrsFormParam) {
+ RequestBody b = o.getRequestBody();
+ if (b == null)
+ o.setRequestBody(b = new RequestBody().content(new Content()));
+ MediaType mdi = b.getContent().computeIfAbsent("application/x-www-form-urlencoded", k -> new MediaType().schema(new Schema<>().type("object")));
+ mdi.getSchema().addProperty(param.value, fillFrom(schema(param.type), annotation));
+ return;
+ }
+
+ Parameter p = new Parameter().name(param.value).schema(fillFrom(schema(param.type), annotation));
if (param instanceof JaxrsHeaderParam)
p.setIn("header");
else if (param instanceof JaxrsQueryParam)
@@ -303,9 +318,16 @@ private Schema> schema(TypeModel type) {
List requied = new ArrayList<>();
s.type("object").setRequired(requied);
ClassModel c = type.asClass();
+ fillFrom(s, c.annotation(io.swagger.v3.oas.annotations.media.Schema.class));
for (FieldModel f : c.fields()) {
- s.addProperty(f.name(), schema(f.type()));
+ if (f.isStatic() || f.isTransient())
+ continue;
+ Optional a = f.annotation(io.swagger.v3.oas.annotations.media.Schema.class);
+ if (a.flatMap(o -> o.member("hidden")).map(o -> o.asBoolean()).orElse(false))
+ continue;
+
+ s.addProperty(f.name(), fillFrom(schema(f.type()), a));
// TODO add required value from jackson
}
// TODO exemple
@@ -313,6 +335,16 @@ private Schema> schema(TypeModel type) {
return new Schema<>().$ref("#/components/schemas/" + n);
}
+ private Schema> fillFrom(Schema> s, Optional annotation) {
+ if (annotation.isEmpty())
+ return s;
+ AnnotationModel a = annotation.get();
+ a.member("name").filter(v -> v.isSet()).ifPresent(v -> s.setName(v.asLiteral()));
+ a.member("title").filter(v -> v.isSet()).ifPresent(v -> s.setTitle(v.asLiteral()));
+ a.member("description").filter(v -> v.isSet()).ifPresent(v -> s.setDescription(v.asLiteral()));
+ return s;
+ }
+
/**
* @param p
* @param httpMethod
@@ -394,4 +426,22 @@ public static AnnotationModel[] findTags(ClassModel m) {
public Map getSchemas() {
return schemas;
}
+
+ private static final class IgnoreOpenapiField extends BeanSerializerModifier {
+ private static final long serialVersionUID = 1L;
+ private static final Set fieldsToIgnore = Set.of("exampleSetFlag");
+
+ @Override
+ public List changeProperties(SerializationConfig config, BeanDescription beanDesc, List beanProperties) {
+
+ // On filtre les propriétés à ignorer
+ List newProps = new ArrayList<>();
+ for (BeanPropertyWriter writer : beanProperties) {
+ if (!fieldsToIgnore.contains(writer.getName())) {
+ newProps.add(writer);
+ }
+ }
+ return newProps;
+ }
+ }
}
\ No newline at end of file
diff --git a/unknow-server-test/unknow-server-test-pojo/src/main/java/unknow/server/http/test/Rest.java b/unknow-server-test/unknow-server-test-pojo/src/main/java/unknow/server/http/test/Rest.java
index 0d4be212..5f1f8740 100644
--- a/unknow-server-test/unknow-server-test-pojo/src/main/java/unknow/server/http/test/Rest.java
+++ b/unknow-server-test/unknow-server-test-pojo/src/main/java/unknow/server/http/test/Rest.java
@@ -18,6 +18,7 @@
import jakarta.ws.rs.HeaderParam;
import jakarta.ws.rs.MatrixParam;
import jakarta.ws.rs.POST;
+import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
@@ -34,32 +35,35 @@ public class Rest {
@GET
@Path("t")
- public void t() throws InterruptedException {
+ @SuppressWarnings("unused")
+ public void t(@PathParam("q") String q) throws InterruptedException {
Thread.sleep(3000);
throw new NullPointerException("test");
}
@GET
@Path("q/{v}")
- public void q() { // ok
+ @SuppressWarnings("unused")
+ public void q(@PathParam("q") String q, @PathParam("v") String v) { // ok
}
- @GET
+ @POST
public void oneWay(@PathParam("q") String q, @BeanParam Bean bean) {
logger.info("oneWay>> q: '{}' bean: {}", q, bean);
}
- @GET
+ @PUT
@Consumes({ "application/json", "application/x-ndjson" })
- public Response response(@PathParam("q") String q, @BeanParam Bean bean) {
- logger.info("response>> q: '{}' bean: {}", q, bean);
+ public Response response(@PathParam("q") String q, @FormParam("k") String k) {
+ logger.info("response>> q: '{}' bean: {}", q, k);
return Response.status(200).entity("echo").build();
}
@POST
@Consumes({ "application/x-protobuf", "application/json", "application/jsonl", "application/x-ndjson" })
@Produces({ "application/x-protobuf", "application/json", "application/jsonl", "application/x-ndjson" })
- public Truc call(Truc truc) {
+ @SuppressWarnings("unused")
+ public Truc call(@PathParam("q") String q, Truc truc) {
return truc;
}
@@ -67,7 +71,8 @@ public Truc call(Truc truc) {
@Path("list")
@Consumes({ "application/x-protobuf", "application/json", "application/jsonl", "application/x-ndjson" })
@Produces({ "application/x-protobuf", "application/json", "application/jsonl", "application/x-ndjson" })
- public Collection list(Collection truc) {
+ @SuppressWarnings("unused")
+ public Collection list(@PathParam("q") String q, Collection truc) {
return truc;
}