I'm using swagger-jersey2-jaxrs to generate swagger.json. This is my java code:
#Path("/example")
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
#ApiImplicitParams({
#ApiImplicitParam(name = "object", required = true, dataTypeClass = MyObject.class, paramType = "body")
})
#ApiOperation(value = "Return one entity", notes = "Returns one entity at random", response = CommonResponse.class)
public String getStuff(String requestString) {...}
And I got this swagger.json file as the result:
"parameters": [
{
"in": "body",
"name": "body", // SHOULD BE REMOVED
"required": false,
"schema": {
"type": "string"
}
},
{
"in": "body",
"name": "object", // I ONLY WANT THIS
"required": true,
"schema": {
"$ref": "#/definitions/MyObject"
}
}
]
As I know String requestString will generate parameter name="body" by default. How can I remove it? I just want my parameter name="object" to be appeared.
By using #ApiParam annotation from io.swagger.annotations you can hide parameters. To do this, set the field hidden to true.
...
public String getStuff(
#ApiParam(hidden = true) String requestString) {...}
Related
i have JSON :
{
"id": "string",
"name": "string",
"port": 0,
"location": "string",
"useCustomLocation": true,
"inMemoryMode": true,
"enabled": true,
"active": true,
"autoStartup": true,
"partitions": [
{
"id": "string",
"name": "string",
"factorUser": {
"username": "string",
"password": "string",
"admin": true,
"perms": "string"
},
"users": [
{
"username": "string",
"password": "string",
"admin": true,
"perms": "string"
}
]
}
]
}
My pojo classes:
public class Root {
private String id;
private String name;
private long port;
private String location;
private boolean useCustomLocation;
private boolean inMemoryMode;
private boolean enabled;
private boolean active;
private boolean autoStartup;
private Partition[] partitions;
//Getter and Setters simple variebles
public Partition[] getPartitions() {
return partitions;
}
public void setPartitions(Partition[] value) {
this.partitions = value;
}
}
Partition class:
public class Partition {
private String id;
private String name;
private User factorUser;
private User[] users;
//Getter and Setters simple variebles
public User getFactorUser() {
return factorUser;
}
public void setFactorUser(User value) {
this.factorUser = value;
}
public User[] getUsers() {
return users;
}
public void setUsers(User[] value) {
this.users = value;
}
}
and the next two classes work similarly(FactorUser and User)
my Test:
public void postBaseData() {
Root root = new Root();
Response response = given()
.contentType(ContentType.JSON)
.log().all()
.auth()
.preemptive()
.basic("login", "password")
.body(root)
.baseUri(BaseUrl + STORE_INSTANCE)
.when()
.post()
.then()
.extract().response();
System.out.println(response.getBody().asString());
Assert.assertEquals(200, response.statusCode());
}
Why is only part of the request sent to me? And therefore returning status code 400
Part of body which posted:
{
"id": null,
"name": null,
"port": 0,
"location": null,
"useCustomLocation": false,
"inMemoryMode": false,
"enabled": false,
"active": false,
"autoStartup": false,
"partitions": null
}
I understand that the error is somewhere in the initialization of nested classes, for example "partition", but I can not understand how to do it correctly.I asked a similar question with get, but for a long time I can’t figure out how to work with such complex json requests. I also tried the line: "private Partition[] partitions" changing to "private List<Partition> partitions" and etc... but I still can't send full json.
i don't use constructor because in POSTMAN i get 200 ok with empty fields
scr
I'm running into an issue with a Json schema validation.
I have a Java class like this
package com.ebc.jackson.exampe.data;
public class FormElement {
private String fieldName;
private String fieldType;
private Object value;
public String getFieldName() {
return fieldName;
}
public void setFieldName(String fieldName) {
this.fieldName = fieldName;
}
public String getFieldType() {
return fieldType;
}
public void setFieldType(String fieldType) {
this.fieldType = fieldType;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
}
I'm using below code to generate the schema:
JsonSchemaGenerator generator =
new JsonSchemaGenerator(objectMapper);
JsonNode schema = generator.generateJsonSchema(FormElement.class);
String strSchema = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(schema);
this code generates below schema
{
"$schema" : "http://json-schema.org/draft-04/schema#",
"title" : "Form Element",
"type" : "object",
"additionalProperties" : false,
"properties" : {
"fieldName" : {
"type" : "string"
},
"fieldType" : {
"type" : "string"
},
"value" : {
"$ref" : "#/definitions/Object"
}
},
"definitions" : {
"Object" : {
"type" : "object",
"additionalProperties" : false,
"properties" : { }
}
}
}
In the request, I could receive a Json Object like
{
"fieldName": "user-name",
"fieldType": "textInput",
"value": "Alex"
}
When I try to validate this object against the Json schema, "value" attribute is not valid, it is expecting a "key: value" pair but, a string is found.
In the Java class the value attribute is Object because it could be a String, Integer, Boolean, etc.
My question is, how can I generate a schema to support different data types for "value" attribute?
You can use the anyOf property of schema :
Try the below one :
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Form Element",
"type": "object",
"additionalProperties": false,
"properties": {
"fieldName": {
"type": "string"
},
"fieldType": {
"type": "string"
},
"value": {
"$ref": "#/definitions/Object"
}
},
"definitions": {
"Object": {
"format": "",
"anyOf": [
{
"type": "object"
},
{
"type": "string"
},
{
"type": "number"
},
{
"type": "integer"
},
{
"type": "boolean",
"x-enumFlags": true
},
{
"type": "null"
}
],
"additionalProperties": false,
"properties": {}
}
}
}
Or you could try the pipe separator in type.In the schema you provided just change the value of type to "type": "string|object|integer|number". This notation didn't work for me in swagger but you can check if it works for you.
I have 2 application which application A is exposing API for application B to consume.
Application A is generating the swagger.json for application B, and application B is using swagger-codegen to generate the model code.
In my application A which is using Jackson with polymorphic with WRAPPER_OBJECT
#JsonTypeInfo (use = JsonTypeInfo.Id.NAME, include =
JsonTypeInfo.As.WRAPPER_OBJECT, property = "type")
#JsonSubTypes({#JsonSubTypes.Type(value = Dog.class, name = "doggy"),
#JsonSubTypes.Type(value = Cat.class, name = "kitty")})
#ApiModel(subTypes = {Dog.class, Cat.class}, discriminator = "type")
public abstract class Animal {
}
#ApiModel(value = "kitty", parent = Animal.class)
public class Cat extends Animal {
public int lives = 9;
}
#ApiModel(value = "doggy", parent = Animal.class)
public class Dog extends Animal {
public double barkVolume = 100d;
}
which expecting the json format to be wrapped.
{
"kitty": {
"lives": 9
}
}
so when application A is generated the swagger.json using springfox, it generated as below.
"Animal": {
"type": "object",
"discriminator": "type",
"title": "Animal"
},
"doggy": {
"title": "doggy",
"allOf": [
{
"$ref": "#/definitions/Animal"
},
{
"type": "object",
"properties": {
"barkVolume": {
"type": "number",
"format": "double"
}
},
"title": "doggy"
}
]
},
"kitty": {
"title": "kitty",
"allOf": [
{
"$ref": "#/definitions/Animal"
},
{
"type": "object",
"properties": {
"lives": {
"type": "integer",
"format": "int32"
}
},
"title": "kitty"
}
]
}
But the problem come when the swagger.json is giving to application B to generate the code, the code generated without wrapped.
#javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2019-08-28T12:54:58.555+08:00")
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type", visible = true)
#JsonSubTypes({#JsonSubTypes.Type(value = Kitty.class, name = "kitty"), #JsonSubTypes.Type(value = Doggy.class, name = "doggy"),})
public class Animal {
}
and when the json is generated as below.
{
"type": "kitty",
"lives": 9
}
i try to check swagger-codegen code, seem that the code alway generated it as JsonTypeInfo.As.PROPERTY.
i just wonder if is that any option in the swagger.json which can define the jackson object can be generated as WARPPER_OBJECT?
How to ignore filed field depending on method?
I have a question about Spring Jackson annotations.
I have a model class. Code:
public class Tenant{
#JsonIgnore
private String id;
#JsonProperty("id")
#JsonDeserialize(using = StringValueDeserializer.class)
private String idSIMC;
#JsonProperty("name")
private String displayName;
#JsonProperty("description")
private String description;
#JsonProperty("default")
private boolean def;
#JsonProperty("geoLoc")
#JsonDeserialize(using = GeoLocationIdNameDeserializer.class)
private GeoLocation geoLoc;
#JsonProperty("asnId")
private String asnId;
#JsonProperty("devices")
#JsonDeserialize(using = StringArrayIdDeserializer.class)
private List<String> tempDevice = Collections.synchronizedList(new ArrayList<>());
#JsonIgnore
#JsonProperty("devices") // <-- I need to add this
private List<Device> devices = Collections.synchronizedList(new ArrayList());
//getters and setters...
}
Now my question. I have method#1 that instance above class and write in tempDevice IDs of devices. method#2 get all devices from servers and filter them by tempDevice (I need to do it) can I annotate ( or something else ) my fields to be ignored as Json Objects depending on method is called?
method#1
public List<Tenant> getTenantsFromServer() {
SSLVerification.disableSslVerification();
ArrayList<Tenant> tenants = new ArrayList<>(0);
String[] ids = getTenantIds();
for(int i=0; i<ids.length; i++){
ResponseEntity<ReturnUnique<Tenant>> result = getRestTemplate().exchange(getUrl() + SIEMCommands.ZONE_GET_ZONE + "?id=" + ids[i],
HttpMethod.GET, new HttpEntity(getHeader()), new ParameterizedTypeReference<ReturnUnique<Tenant>>(){});
Tenant newTenant = result.getBody().getValue();
newTenant.setParentNode(this);
newTenant.generateId();
tenants.add(newTenant);
}
return tenants;
}
In this method i have a key "devices" in that is stored id. In method#2 another json that also have "devices" key but with another dates.(name,ip, etc.) And when I execute this method I should to store all in devices list.
JSON used in first method#1
{"return": {
"asnId": 0,
"default": false,
"description": "",
"devices": [
{"id": 144121785900597248},
{"id": 144121785917374464},
{"id": 144121785934151680}
],
"geoLoc": {
"id": {"value": 0},
"name": ""
},
"id": {"value": 1},
"name": "HA_Zone"
}}
devices values are written in tempDevice;
method#2 use this JSON
"devices": [{
"CRuleRight": true,
"FTestRight": true,
"adRight": true,
"addDeleteRight": false,
"children": [],
"clientCount": 0,
"clientStatus": "0",
"clientVipsInSync": false,
"deviceActionRight": true,
"deviceDisabled": false,
"elmFile": false,
"elmHasSAN": false,
"eventRight": true,
"hostname": "",
"ipAddress": "172.28.60.17",
"ipsID": "144121785950928896",
"ipsRight": true,
"name": "ASA Admin CTX Site 2",
"parent": false,
"polRight": true,
"protocol": "gsyslog",
"reportRight": true,
"status": "6",
"statusAck": "0",
"tpcCollector": "syslog",
"tpcType": "278",
"type": "VIPS",
"viewRight": true,
"vipsEnabled": true,
"vipsID": "49",
"vipsInSync": false
},
{
"CRuleRight": true,
"FTestRight": true,
"adRight": true,
"addDeleteRight": false,
"children": [],
"clientCount": 0,
"clientStatus": "0",
"clientVipsInSync": false,
"deviceActionRight": true,
"deviceDisabled": false,
"elmFile": false,
"elmHasSAN": false,
"eventRight": true,
"hostname": "",
"ipAddress": "172.28.13.10",
"ipsID": "144121785179176960",
"ipsRight": true,
"name": "ASA-VPN-DC1",
"parent": false,
"polRight": true,
"protocol": "gsyslog",
"reportRight": true,
"status": "0",
"statusAck": "0",
"tpcCollector": "syslog",
"tpcType": "278",
"type": "VIPS",
"viewRight": true,
"vipsEnabled": true,
"vipsID": "3",
"vipsInSync": false
}
}]
this dates i have to write in devices
If I understand correctly, you are looking for a way to deserialize 2 different json datatype having same property name into a object in different situation. If that is the case, the suggestion of using JacksonMixInAnnotations from #Thomas should work. JacksonMixInAnnotations can provide a kind of way to add annotation from another class (called mix-in class) to the target class during run time.
In your case, you can left tempDevice and devices without Jackson annotation like follows:
public class Tenant {
private List<String> tempDevice;
private List<Device> devices;
}
and declare 2 mix-in classes:
abstract class TempDeviceMixIn {
#JsonProperty("devices")
private List<String> tempDevice;
}
abstract class DeviceMixIn {
#JsonProperty("devices")
private List<Device> devices;
}
When you need to deserialize a json string with a string property of devices, you can add mix-in class annotation likes:
ObjectMapper mapper = new ObjectMapper();
mapper.addMixInAnnotations(Tenant.class, TempDeviceMixIn.class);
Tenant tenant = mapper.readValue(json, Tenant.class);
Deserialize a json string with a object property of devices is similar.
As you are using RestTemplate, you will need a MappingJacksonHttpMessageConverter with your ObjectMapper.
Trying to serialize a collection of non-primitive types using katharsis, but getting an empty collection all the time.
Response example:
{
"data": {
"type": "products",
"id": "1",
"attributes": {
"simpleAttributes": [
{}
],
"variationGroup": "variationGroup"
},
"relationships": {},
"links": {
"self": "http://localhost:8080/api/products/1"
}
},
"included": []
}
Expected response:
{
"data": {
"type": "products",
"id": "1",
"attributes": {
"simpleAttributes": [
{
tittle: "some title",
value: "some value"
}
],
"variationGroup": "variationGroup"
},
"relationships": {},
"links": {
"self": "http://localhost:8080/api/products/1"
}
},
"included": []
}
Domain objects (getters, setters, constructor and other stuff omitted by using lombok #Data annotation):
#JsonApiResource(type = "products")
#Data
public class Product {
#JsonApiId
private Integer id;
private List<SimpleAttribute> simpleAttributes = new ArrayList<>();
private String variationGroup;
}
#Data
public class SimpleAttribute implements Serializable{
private String title;
private String value;
}
I do not want to use relationships in this case or to include attributes to "included" field. Is it possible in katharsis?
Not sure what actually was wrong, but the problem disappeared after I changed katharsis-spring version from 2.3.0 to 2.3.1.