Does anyone know if it's possible to create an example post body with pre-populated/default values from Java annotations? My goal is for users to have a working example when viewing a POST endpoint in Swagger UI. Ideally this working example is created from annotations in the code.
For Example on a model object property:
#ApiModelProperty(example = "http://istock.com/my_cool_image")
#JsonProperty("submitted-image-url")
private String submittedImageUrl;
Would produce something like this in Swagger UI (note the example URL shows up in the Model Schema):
The way it appears to be designed, you have to click on Example Value under Data Type for the request/Value textarea to be populated (at least in Swagger 1.5.9).
Related
We are using Swagger to model our API with Spring annotations:
#Operation(summary = "Creates a post for given user.")
#PostMapping("/post")
open fun createPost(
#RequestParam("userId") user: User,
)
The issue we are having is that Swagger does not know there is a logic behind and we are only passing userId: Long for which the user is loaded by Hibernate.
The model of User contains several #OneToOne, #ManyToOne, #OneToMany relations to other entities and Swagger builds the model of User with all of them. This causes the model to be huge and some of our Swagger docs wouldn't even load in the browser as the model is in the size of megabytes.
Is there a way to tell Swagger:
to ignore specific entity/entities
to enforce different type (in this case Long)
Ideally something like:
#Operation(summary = "Creates a post for given user.")
#PostMapping("/post")
open fun createPost(
#SwaggerType(Long::class)
#RequestParam("userId")
user: User,
)
The cleanest way is to use Springfox with an alternate type rule. See no 10 in the examples given here:
https://springfox.github.io/springfox/docs/current/#springfox-spring-mvc-and-spring-boot
This enables you to completely replace your User class by any other (fake) class that you want to show to the Swagger user, without polluting your model with workarounds - but still staying transparent in your code.
There are a few options that can be tried:
Using inheritance with User Model, you can just define a SuperClass-childClass mapping with User class only containing the userId, and the child class that inherits from it will be holding the other attributes for you. In this way, the input will only be the userId with minimal effort.
Using JsonIgnore, but this works really well while returning the response.
With OpenAPI, Swagger has introduced the capability to use specific properties from the request class. More can be read from
https://swagger.io/docs/specification/describing-request-body/
you can use two different class,a basic class and a senior class,and the senior extends the basic,use basic class in API;
or you can use #JsonIgnore if you don't want to show the field ,like:
#JsonIgnore
private String name;
Beacuse Swagger use jackson to json, if you shield the field by jackson,it will not appear.
In swagger
you can use #ApiModelProperty(hidden = true),This is the perfect way
I used swagger code gen to generate models for a REST application.
The JSON representation of the model it should be generating looks like
[ object1, object2, object3 ]
But swagger code gen represents a schema that is just a list of another object as something like this in the code:
Things extends ArrayList<thing>
Spring fox isn't recognizing this object when it generates the swagger file / api info page. Something about doing "extends ArrayList" is causing it to be confused. Writing the swagger file in swagger editor produces a valid model, but the code generated from swagger code gen does not.
I can hand write the model to contain an object that is List and that should resolve the problem, but then my swagger file that I'm using for code generation won't be accurate.
Is there a secret to get this to work properly? I'm wondering if there's something I should be adding to the Docket to get it to register this properly.
What should my swagger file look like if I'm using swagger code gen to generate code for use in spring fox if the response body for one operation is an array of a single type of object? (An array of multiple types of objects actually seems to work fine, it's just when it's only a single object that it has problems.
I resolved my issue by modifying the schema in the request section to be of type array rather than specifying it in my model declarations and it resolved the issue for JSON responses. Though the XML response didn't provide useful information (just said a blank xml response will be sent back) but it's fine for me because my project is only using JSON.
I'm working on documenting an API made with RESTeasy + Jackson in Java using Swagger/OpenAPI (version 1.5.18 - I did add in v3 OAS 2.0.1 to try oneOf/anyOf). One of the endpoints takes in a String as a request body, which is then transformed into one of several classes. The documentation needs to display each of these models so that users can see them. The models are defined in another project. Is there a way to do this through annotations? The closest thing I've found is adding #RequestBody(content=#Content(schema=#Schema(oneOf= {class1.class, class2.class}))) but haven't been able to get it to add the model using that. I also tried adding a dummy class with #ApiModel(subTypes={class1.class, class2.class}. I don't want to add additional endpoints for each object type due to code maintainability.
My question is: is it possible to add the models through annotations while leaving the input type as String?
Here is the relevant code:
#POST
#Path("/{filetype}/new")
#Consumes("application/json")
public Response writeFile(
#ApiParam(required=true, allowableValues = "class1, class2") #PathParam("filetype") String filetype,
#RequestBody(content=#Content(schema=#Schema(oneOf= {class1.class, class2.class}))) String inputFile
) {
return validateFileAndSaveToServer(filetype, inputFile);
}
I am attempting to mold Swagger-UI in order to modify not only that "name" field but also the "Description" field of an API input parameter. An example is here of someone appearing to do this successfully, utilizing both #ApiParam and #RequestParam: [link]
The closest to modifying the description field I have come so far is the following, where I used the "value" field alone on the #RequestParam input:
However, whenever I try to implement the same structure utilizing both #ApiParam and #RequestParam annotations on a single input element, as shown on the example of the other user above, I get the following error:
Any idea what I'm doing wrong with the annotations here? Is it that this can't be done on a #RequestMapping annotated API?
You are missing a , In between #ApiParam value and name properties
#ApiParam(value="Use GET...", name="schoolId")
Guys, Well I have done enough research still I can't find the solution to this.
In a nutshell, I'm simply passing url encoded form data to the Controller method and trying to convert it as a domain object which has Date and integers.
#RequestMapping(value = "/savePassport", method = RequestMethod.POST)
public #ResponseBody
AjaxResponse savePassport(#RequestBody StaffPassport passport, HttpServletResponse response) {
// Some operations.
}
The Staff Passport looks like this:
import java.sql.Date;
public class StaffPassport {
private int staffId;
private String passportNumber;
private String placeOfIssue;
private Date issueDate;
private Date expiryDate;
private String spouseName;
private String oldPassportRef;
private String visaInfo;
private String description;
//gets/sets
}
When I invoke the /savePassport, I get unsupported media exception. I guess it's related to casting.
I can't this working right. Of course I can catch individual form data using #RequestParam and manually do the casting but that's not the point of a framework isn't it?
Where am I going wrong? And you are right. I'm a beginner in Spring, but I love it.
Looks like you're using the wrong annotation. #RequestBody is for taking a request that has arbitrary content in its body,such as JSON, some application defined XML, comma separated variables.. whatever. And using a marshaller that you configure in the dispatcher servlet to turn it into objects.
If all you want to do is ask Spring to bind a plain old form post onto the backing object for you, the correct annotation to put on the method parameter is #ModelAttribute.
If you are posting a JSON Object with jQuery and you want Spring to be able to process it with #RequestBody, use JSON.stringify(....) in your data. Here an example:
var data = { "id": 3, "name": "test" }
$.post("processJsonData.html",JSON.stringify(data), function(data){
...
}
);
If you don't use the JSON.stringify() then you will submit the data as form data and Spring will tell you that you have an unsupported media type.
First of all be sure that you have
<mvc:annotation-driven />
in your Spring configuration file. This is mandatory for working with JSOn in SPring MVC.
Second, I recommend you to test wether request to the server has application/json content type. I belive Fiddler2 will help you to do so.
Third, but I'm not sure about it, Try to change Date items in your POJO from SQL type to regular java type.
UPDATE:
just looked at the Form and it seems like your "Accept" HTTP Header should be also application/json. Please test this issue with Fiddler2 as well.
I assume that you are posting JSON and want Spring to convert to StaffPassport. If you are getting an Unsupported media exception, it is because Spring could not figure out an appropriate way to perform the conversion.
For Spring to convert JSON, it needs Jackson -- make sure you have the Jackson jars in your project. If this is a Maven based project you can add the jackson-mapper-asl artifact ID to your pom.xml. This should give you the jackson-mapper and jackson-core jars.
Edit: I should mention that this applies to Spring 3 (I recently ran into this problem). I'm not sure what else is required for previous versions of Spring.
Check into HttpMessageConverter interface and its implementations. You could write your own implementation of it to convert it to the domain model you want. By the time the control gets to your method, you can access it as if your domain model object is passed.
Ok, I think I should refine my answer. I do not have direct experience of using it in a spring-mvc project but spring-integration. I am pretty sure the applicable media type (application/x-url-form-encoded) is already handled and converted to MultiMap by Spring framework; so, retrieve the values from that just like any other map with the key value being your form variable and populate your business model.
HTH.