Using swagger editor I created a post call to consume a json object that I want to simply load into a db but when I run the call I get an empty json object.
This is the parameters portion of my json swagger for the post
"parameters": [
{
"in": "body",
"name": "body",
"description": "Add question to collection",
"required": true,
"schema": { "type" : "object", "additionalProperties" : {}
}
}
],
It then creates a "Body" model, but I am not able to see the json that was part of the post:
#javax.annotation.Generated(value = "class io.swagger.codegen.languages.JaxRSServerCodegen", date = "2016-01-22T20:49:03.229Z")
public class Body {
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Body body = (Body) o;
return true;
}
#Override
public int hashCode() {
return Objects.hash();
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("class Body {\n");
sb.append("}");
return sb.toString();
}
/**
* Convert the given object to string with each line indented by 4 spaces
* (except the first line).
*/
private String toIndentedString(Object o) {
if (o == null) {
return "null";
}
return o.toString().replace("\n", "\n ");
}
}
If I remove the text/json from consume and generated my code again and I still see an issue with the body model and being able to pull in json.
If you look at the toString method it shows hard coded values, so I dont see how I can pull the json from the post with the post method only taking in the Body and securitycontext.
I am a little confused about the http accept, when using this swagger snippet:
"post": {
"tags": [
"AskGrey"
],
"summary": "Create new askgrey.com question",
"operationId": "postAskGrey",
"consumes": [
"application/json",
"text/json"
],
"produces": [
"application/json"
],
"parameters": [
{
"in": "body",
"name": "body",
"description": "Add question to collection",
"required": true,
"schema": { "type" : "object", "additionalProperties" : {}
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "object"
}
}
},
"deprecated": false
}
The method generated is the following:
#Override
#POST
#Consumes("application/json")
public Response postAskGrey(Body body,SecurityContext securityContext)
throws NotFoundException {
So based on all this I am not sure how to pull in the post body info, normally I would grab what I need from the http request but with swagger I cant seem to figure out how that gets used.
Before you send your data you should check HTTP ACCEPT method which you set in swagger when you send your data.
There should be Several Accept method which their behaviour distinct from each other when sending data to server.
Thus for application/JSON : Data are part of body.
form-data and x-www-form-urlencoded : Data are part of header.
I haven't adaquate Java experience to give correct code to obtain json into related jSON Object but How to convert HTTP Request Body into JSON Object in Java this answer could help.
Please Check following RFCs for further information
form-data related RFC https://www.rfc-editor.org/rfc/rfc7578
x-www-form-urlencoded related RFC https://datatracker.ietf.org/doc/html/draft-hoehrmann-urlencoded-01
application/JSON related rfc https://www.ietf.org/rfc/rfc4627.txt
UPDATED
Related curl command : I get the command from swagger live demo http://petstore.swagger.io/#/pet paste your json to it and change url, secret key give it a try!
curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{
"id": 0,
"category": {
"id": 0,
"name": "string"
},
"name": "doggie",
"photoUrls": [
"string"
],
"tags": [
{
"id": 0,
"name": "string"
}
],
"status": "available"
}' 'http://petstore.swagger.io/v2/pet?api_key=special-key'
Related
I get below JSON string as a request body for my REST API. I don't like this JSON structure, but I don't have any control on this. It's somebody else posting this message and I have to create a REST API (POST method) and consume this message in my API. So I have to deserialize this into Java objects in my REST controller. It has list of lists objects. I tried several ways with fasterxml, but I was not successful.
{
"messages": [
[
{
"message": "message1_a",
"info": {
"timestamp": "2521013204"
}
},
{
"message": "message1_b",
"info": [
{
"message": "message1_c",
"info": {
"id": "asfa-14fs-df"
}
},
{
"message": "message1_d",
"info": {
"reason": "msg_reason",
}
}
]
}
]
]
}
Can anybody help me how my Java POJOs should look like?
It seems like a array of message.
In Java you can use Spring to transform the Json to a Object.
String url = "http://your/json/url";
ResponseEntity<Message[]> responseEntity = new RestTemplate().getForEntity(url, Message[].class);
Be sure that your entity has all the attributes of Json.
The doc: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html
{
"context": {
"headers": {},
"entity": {
"validationDetailsEntityList": [
{
"createTimestamp": 1512653225936,
"modifyTimestamp": 1512653225936,
"version": 0,
"auditTimestamp": "2"
},
{
"createTimestamp": 1512652876650,
"modifyTimestamp": 1512652876650,
"version": 0,
"auditTimestamp": "2"
},
{
"createTimestamp": 1512652955832,
"modifyTimestamp": 1512652955832,
"version": 0,
"auditTimestamp": "2"
}
]
}
"entityType":"com.example.demo.wrapper.ABCDWrapper",
"entityAnnotations": [],
Class Written below to get the response on the http mapped request
#RequestMapping(value = "/fetch", method = RequestMethod.POST)
public Response getAllXYZDetails(#RequestBody QueryDetails queryDetailsPayLoad) {
List<XYZEntity> xyzEntityList = xyzService.getAllXYZDetails();
return Response.ok(xyzEntityList)
.build();
}
I am trying to build a generic response type from my controller class on http REST calls, and so my return type is Response.
Now, what's happening is that:
The response generated not only has the details that I want in json but also it is having a lot of extra information like
entityType and entityAnnotations etc etc(SEE ABOVE RESPONSE), which I don't want.
How to get rid of those ans get only the entities in response?
If you are using Jackson annotations you can configure pretty much everything. In your case, #JsonIgnore should suffice.
If you are using JAX-RS/JAXB then Add #JsonIgnoreProperties(ignoreUnknown = true) on top of your class
I am using wiremock for REST API testing and I am facing the below problem.
I have the following 2 json requests created.
REQUEST 1:
{
"request": {
"method": "GET",
"urlPattern": "/api/v1/user/2158634832/ishop.*",
"headers": {
"Accept": {
"contains": "application/json"
},
"X-RequestId": {
"matches": ".*"
},
"X-SecurityToken": {
"matches": "valid_secure_token"
}
}
},
"response": {
"status": 200,
"jsonBody": {
"user": {
"ID": "5cc1b131-8858-4870-a7ce-fd37aa805ebf",
"info": [
{
"kid": "2f0ad36a-9f23-427c-9a15-16d240385b87",
"cid": 10962435,
"pid": "V",
"contactid": 11812026,
"created": "2017-04-26T00:08:25.926",
"lastModified": "2017-04-27T00:01:45.047",
}
]
}
},
"headers": {
"Content-Type": "application/json"
}
}
}
My Get Request for the above wiremock looks something like this
**/api/v1/user/2158634832/ishop?ID=9879cfde-e353-4722-a91e-f22d29d8195c**
Request 2 :
{
"request": {
"method": "GET",
"urlPattern": "/api/v1/user/2158634832/ishop/status.*",
"headers": {
"Accept": {
"contains": "application/json"
},
"X-RequestId": {
"matches": ".*"
},
"X-SecurityToken": {
"matches": "valid_secure_token"
}
}
},
"response": {
"status": 200,
"jsonBody": {
"userstatus": {
"id": "5cc1b131-8858-4870-a7ce-fd37aa805ebf",
"type": "ishop",
"status" : "active",
"lastModifiedTime": "2017-04-27T00:01:45.047",
"allowedChange": "true"
}
},
"headers": {
"Content-Type": "application/json"
}
}
}
my Get request for the above looks something like this
/api/v1/user/2158634832/ishop/status?ID=9879cfde-e353-4722-a91e-f22d29d8195c
the problem here is that at times due to the similar URL Pattern for Request 1 and Request 2 what is happening is at times
When I submit a request for Request 1, I am getting the response which is of Request 2.
Can anyone suggest me a workaround how can i fix this ? I am hoping something to do with matches and urlPattern and somehow i can eleminate the status call in the first request i can do it, but not sure how.
any suggestions ?
Since one of your request URLs contains the other, a regex matching the shorter one will also match the longer one. I suspect this is why the shorter one is being matched when you'd prefer the longer one.
I suggest being more specific with your URL matches e.g.
"urlPath": "/api/v1/user/2158634832/ishop" in the first stub and
"urlPath": "/api/v1/user/2158634832/ishop/status" in the second
These will still match despite you not specifying the ID query param. WireMock treats extra headers or query parameters without match parameters as "don't care, match anyway".
Well i fixed it in the following way
Request 1 changed from
"urlPattern": "/api/v1/user/2158634832/ishop.*",
to
"urlPath": "/api/v1/user/2158634832/ishop",
Request 2 changed from
"urlPattern": "/api/v1/user/2158634832/ishop/status.*",
to
"urlPath": "/api/v1/user/2158634832/ishop/status",
A better solution is to use stub priority:
http://wiremock.org/docs/stubbing/#stub-priority
This way you can still use urlPatten
{
"priority" : 2,
"request": {
"method": "GET",
"urlPattern": "/api/v1/user/2158634832/ishop.*",
"headers": {
...
and:
{
"priority" : 1,
"request": {
"method": "GET",
"urlPattern": "/api/v1/user/2158634832/ishop/status.*",
"headers": {
...
In MVC, you would expect that controller will receive models as input and produce models as output. In Swagger, the latter is not a problem but I have troubles with former. I can't understand how to make Swagger build an input model from incoming GET parameters.
Consider:
"paths": {
"/search": {
"get": {
"consumes": [],
"produces": [
"application/json"
],
"parameters": [
// What goes here?
],
"responses": {
"200": {
"description": "Success",
"schema": {
"$ref": "#/definitions/SearchResponse"
}
},
}
}
}
}
How do I make the generated controller's method to have a signature like:
public ResponseEntity<ResultModel> controllerGet(ModelFromParameters input);
where ModelFromParameters will have several fields corresponding to different GET parameters.
Examples mostly focus either on POST requests, or GET requests where every of 20-odd parameters are stuffed in the arguments list of method, which is obviously anti-MVC.
The API in question is a complex stateless querying system with a lot of parameters.
Assumption: you want to create an object as parameter to your service method but still pass each of the fields of the object as query parameter in the actual http request and be able to document individual fields in swagger.
e.g. GET http://localhost:8080/search?parameter1=value1¶meter2=value2
Typical Service Method Definition where each query param is defined as a parameter in the actual method
#RequestMapping(method = RequestMethod.GET)
public ResponseEntity<List<String>> search(#RequestParam parameter1, #RequestParam parameter2) {
...
}
Modified service method with single parameter using Object (a.k.a Bean) annotated with #ModelAttribute. Though it is an object, as far as the REST API is concerned it is still the same as above.
#RequestMapping(method = RequestMethod.GET)
public ResponseEntity<List<String>> search(#ModelAttribute FormParam formParam) {
...
}
FormParam class. You can document each field using #ApiParam
public class FormParam {
#ApiParam(value = "parameter1 - description here", required = true)
private String parameter1;
#ApiParam(value = "parameter2 - description here", required = true)
private String parameter2;
//define getter setters below
}
This is how it appears in swagger
This is the generated swagger.json snippet
"paths": {
"/search": {
"get": {
"tags": ["search-service"],
"summary": "Search with Object as parameter",
"description": "Search with Object as parameter",
"operationId": "searchUsingGET",
"consumes": ["application/json"],
"produces": ["*/*"],
"parameters": [{
"name": "parameter1",
"in": "query",
"description": "parameter1 - description here",
"required": true,
"type": "string"
},
{
"name": "parameter2",
"in": "query",
"description": "parameter2 - description here",
"required": true,
"type": "string"
}],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"type": "string"
}
}
},
"401": {
"description": "Unauthorized"
},
"403": {
"description": "Forbidden"
},
"404": {
"description": "Not Found"
}
}
}
},
If you are manually creating the swagger.json the query parameters can be documented like
"parameters": [{
"name": "parameter1",
"in": "query",
"description": "parameter1 - description here",
"required": true,
"type": "string"
},
{
"name": "parameter2",
"in": "query",
"description": "parameter2 - description here",
"required": true,
"type": "string"
}],
I think you can't. I had also a similar problem, for list page + search, using GET with body. No way to make swagger represent this, also if it works in Tomcat; also Elasticsearch supports it. It looks like there is no plan to change this aspect in swagger. I resorted to split the two in swagger: list-without-search as GET and list+search as POST, just to put the page in the swagger documentation, also if the latter actually works also as GET.
I have no experience with swagger code generation but, if your configuration generates what you expect with POST but it doesn't with GET, then you are probably hitting the same limitation.
https://github.com/swagger-api/swagger-ui/issues/2867
https://github.com/swagger-api/swagger-ui/issues/2136
https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.md#operationRequestBody
The requestBody is only supported in HTTP methods where the HTTP 1.1 specification RFC7231 has explicitly defined semantics for request bodies. In other cases where the HTTP spec is vague, requestBody SHALL be ignored by consumers.
In usual, http server(eg. tomcat, jetty) will not accept a body message within a get request. If client needs pass parameters to server by http get method, it should use query string . Last part of the url after '?' character. Query string details you can see query string
But with spring mvc help, your http request parameters in query string will be bound to your controller method parameter`s fields.So it seems like client passed a pojo parameter to server side.
Any way the parameter part should look like this:
"parameters" : [ {
"name" : "age",
"in" : "query",
"required" : false,
"type" : "integer"
}, {
"name" : "firstName",
"in" : "query",
"required" : false,
"type" : "string"
}]
Please note that "in" filed's value is "query". That means parameter is passed by query string.
I supose what you require is posting your arguments in request body, it goes like this:
...
{
"name": "files",
"in": "body",
"required": true,
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/FileRequest"
}
}
}
which translates to:
public Response storageFilePost(
#NotEmpty(message = "systemID is required!") #QueryParam("systemID") final String systemID,
#NotNull(message = "qParam is required!") #QueryParam("qParam") final Long qParam,
#NotNull(message = "files are required!") final List<FileRequest> files) {
I've got the JSON data behind the scenes, that's it
[{"aid":100000,"name":"JYCM201609010250","rtsp":"947|100000|3750","statuz":"1","updateTime":"2017-05-31"},{"aid":100001,"name":"gui","rtsp":"947|100000|3750","statuz":"0","updateTime":"2017-05-31"}]
Background and foreground code are as follows
#Autowired
private MediaImpl media;
#ResponseBody
#RequestMapping(value = "/media",method = RequestMethod.GET)
public List<Media> MediaAll(){
System.out.println("------------------------------------------------------");
return media.findAll();
}
JS code is as follows
<script>
$(document).ready(function () {
$('#table_id_example').DataTable({
"iDisplayLength": 10,
"bLengthChange": false,
"ajax": {
"url": "/media",
"dataType": "json",
"success": function (json) {
console.log(json)
}
},
"columns": [
{
"data": 'aid'
},
{
"data": 'name'
},
{
"data": 'rtsp'
},
{
"data": 'statuz'
},
{
"data": 'updateTime'
}
]
});
});
html code is as follows
The console code
VM178:10 (2) [{…}, {…}]0: {aid: 100000, name: "JYCM201609010250", rtsp: "947|100000|3750", statuz: "1", updateTime: "2017-05-31"}1: {aid: 100001, name: "gui", rtsp: "947|100000|3750", statuz: "0", updateTime: "2017-05-31"}length: 2__proto__: Array(0)
There is no error in the front-end console, and no errors in the back end.But the data is not available
There are a couple of problems here. The first is that datatables expects data in a data element of the json response, such as:
{
data: [{"aid":100000,"name":"JYCM201609010250","rtsp":"947|100000|3750","statuz":"1","updateTime":"2017-05-31"},{"aid":100001,"name":"gui","rtsp":"947|100000|3750","statuz":"0","updateTime":"2017-05-31"}]
}
You should be able to use ajaxSrc: "" on your DataTable settings.
The second problem is with your ajax settings. DataTables states you can not supply the success callback in the ajax settings as it uses this internally.
Documentation on both of these issues:
https://datatables.net/reference/option/ajax
Assuming you are using DataTables 1.10.x