I have a project with Spring MVC and Spring boot.
I use Swagger springfox to document my json service. I have a class with java.sql.Time and java.util.Date attributes.
When I call the api, the class appears like this :
"TranslationLabel":{
"properties":{
"change_date":{
"type":"string",
"format":"date-time"
},
"change_time":{
"$ref":"#/definitions/Time"
}
},
"description":"Traduction de libell茅"
}
In swagger UI, the Model Schema is like this :
{
"change_date": "2015-10-29",
"change_time": {
"date": 0,
"day": 0,
"hours": 0,
"minutes": 0,
"month": 0,
"seconds": 0,
"time": 0,
"timezoneOffset": 0,
"year": 0
}
}
I want to display the "change_time" like "15:31".
To do this, I think I need to use a ModelConverter. So I create a custom converter class based on this example : https://github.com/swagger-api/swagger-core/blob/master/modules/swagger-core/src/test/java/io/swagger/model/override/CustomConverterTest.java
But I don't find how to use it.
Here is my class :
class CustomConverter implements ModelConverter {
@Override
public Property resolveProperty(Type type, ModelConverterContext context, Annotation[] annotations,
Iterator<ModelConverter> chain) {
final JavaType jType = Json.mapper().constructType(type);
if (jType != null) {
final Class<?> cls = jType.getRawClass();
if (cls.equals(Time.class)) {
HashMap<PropertyBuilder.PropertyId, Object> map =
new HashMap<>();
map.put(PropertyBuilder.PropertyId.FORMAT,"HH:mm");
map.put(PropertyBuilder.PropertyId.TYPE,"time");
map.put(PropertyBuilder.PropertyId.EXAMPLE,"12:30");
return PropertyBuilder.build("Time", "hh:mm", map);
} else {
return chain.next().resolveProperty(type, context, annotations, chain);
}
} else {
return null;
}
}
@Override
public Model resolve(Type type, ModelConverterContext context, Iterator<ModelConverter> chain) {
return chain.next().resolve(type, context, chain);
}
}
Now I need to add my converter to the ModelConverters.
ModelConverters converters = new ModelConverters();
converters.addConverter(new CustomConverter());
I did not find any documentation about where to put this code.
Where did I need to put this ?
Springfox has a different way of acheiving this. You need to use the Docket.directmodelSubstitute(Time.class, String.class)
to define an equivalent converter. However it doesn't support examples etc.
Thanks for your answer.
I try your solution but with this, it display "change_time":"string" instead of "change_time":"hh:mm".
Is it possible to specify a format for the String ?
Hi Guys,
I am having a problem related to ModelConverters. My Swagger.json contains a generic class in the expanded form like below:
"JsonNode": {
"type": "object",
"properties": {
"floatingPointNumber": {
"type": "boolean",
"default": false
},
"valueNode": {
"type": "boolean",
"default": false
},
"bigInteger": {
"type": "boolean",
"default": false
},
"textual": {
"type": "boolean",
"default": false
},
"boolean": {
"type": "boolean",
"default": false
},
"containerNode": {
"type": "boolean",
"default": false
},
"missingNode": {
"type": "boolean",
"default": false
},
"object": {
"type": "boolean",
"default": false
},
"pojo": {
"type": "boolean",
"default": false
},
"number": {
"type": "boolean",
"default": false
},
"integralNumber": {
"type": "boolean",
"default": false
},
"short": {
"type": "boolean",
"default": false
},
"int": {
"type": "boolean",
"default": false
},
"long": {
"type": "boolean",
"default": false
},
"double": {
"type": "boolean",
"default": false
},
"bigDecimal": {
"type": "boolean",
"default": false
},
"float": {
"type": "boolean",
"default": false
},
"nodeType": {
"type": "string",
"enum": [
"ARRAY",
"BINARY",
"BOOLEAN",
"MISSING",
"NULL",
"NUMBER",
"OBJECT",
"POJO",
"STRING"
]
},
"binary": {
"type": "boolean",
"default": false
},
"array": {
"type": "boolean",
"default": false
},
"null": {
"type": "boolean",
"default": false
}
}
}
Now this is definitely what I don't want. In fact what I want is to prevent this specific class (com.fasterxml.jackson.databind.JsonNode) (and any other of my choice) to be ever expanded. So in order to do this I used the inbuilt function provided in the io.swagger.converter.ModelConverters class shown below:
public void addClassToSkip(String cls) {
LOGGER.warn("skipping class " + cls);
this.skippedClasses.add(cls);
}
Now having done this I can't seem to figure out where to actually inject the ModelConverters class, as I tried to add it to list of providers along with others but to no result. Can someone please help me with this. I have been looking for the answer for almost 3 days now.
Use a custom converter, this is a bug per my analysis, you can copy ModelResolver to your own code and do something like this.
ModelConverters.getInstance().addConverter(new ModelResolver(mapper));
Further in the ModelResolver modify following resolve method
private Model resolve(JavaType type, ModelConverterContext context, Iterator<ModelConverter> next) {
if (type.isEnumType() || PrimitiveType.fromType(type) != null) {
// We don't build models for primitive types
return null;
}
if (type instanceof SimpleType && ((SimpleType) type).getRawClass().getName().startsWith("your classname")) {
return yourConverter.resolve(type, context, next);
}
It's a hack, issue is same as https://github.com/swagger-api/swagger-core/issues/2260
Most helpful comment
Springfox has a different way of acheiving this. You need to use the
Docket.directmodelSubstitute(Time.class, String.class)
to define an equivalent converter. However it doesn't support examples etc.