There is currently no documentation on the recommended approach for overriding the data model and configuring custom type resolution. Where swagger 1.3 gave some information on several solutions, e.g. by adding an OverrideConverter instance to ModelConverters, and even included some converters for the most commonly used JodaTime types to be resolved to JSON "string : date(-time)", there is nothing in the 1.5 docs or migration guide.
In your community forum Ron/webron kindly pointed me in the direction of the ModelConverter test cases in swagger-core. I reckon it would be helpful to document this approach.
Cheers, Andreas
I'm having some trouble grok-ing the test cases. Would you share a gist of your JodaTime converter?
Sure, no worries.
In our swagger configuration code I'm registering our CustomModelConverter:
ModelConverters.getInstance().addConverter(new CustomModelConverter());
The converter and referenced types are as follows:
public class CustomModelConverter implements ModelConverter {
@Override
public Property resolveProperty(Type type, ModelConverterContext context, Annotation[] annotations, Iterator<ModelConverter> chain) {
JavaType _type = Json.mapper().constructType(type);
if (_type != null) {
Class<?> cls = _type.getRawClass();
if (DateTime.class.isAssignableFrom(cls)) {
return new ISODateTimeProperty();
}
if (LocalDate.class.isAssignableFrom(cls)) {
return new ISODateProperty();
}
if (LocalTime.class.isAssignableFrom(cls)) {
return new ISOTimeProperty();
}
if (Currency.class.isAssignableFrom(cls)) {
return new CurrencyProperty();
}
if(Throwable.class.equals(cls)) {
return new io.swagger.models.properties.ObjectProperty();
}
}
if (chain.hasNext()) {
return chain.next().resolveProperty(type, context, annotations, chain);
} else {
return null;
}
}
@Override
public Model resolve(Type type, ModelConverterContext context, Iterator<ModelConverter> chain) {
if (chain.hasNext()) {
return chain.next().resolve(type, context, chain);
} else {
return null;
}
}
}
public class CurrencyProperty extends AbstractProperty {
public CurrencyProperty() {
this.setType("string");
this.setExample("AUD"); //ISO 4217 currency code
}
}
public class ISOTimeProperty extends AbstractProperty {
public ISOTimeProperty() {
this.setType("string");
this.setExample("23:59:59.999"); //time in ISO8601 format (HH:mm:ss.SSS)
}
}
public class ISODateProperty extends AbstractProperty {
public ISODateProperty() {
this.setType("string");
this.setFormat("date");
this.setExample("1999-12-31"); //date in ISO8601 format (yyyy-MM-dd)
}
}
public class ISODateTimeProperty extends AbstractProperty {
public ISODateTimeProperty() {
this.setType("string");
this.setFormat("date-time");
this.setExample("1999-12-31T23:59:59.999+11:00"); //date-time in ISO8601 format (yyyy-MM-ddTHH:mm:ss.SSSZZ)
}
}
Using this approach java Currency and the joda types DateTime, LocalDate and LocalTime are documented with the same format as we use in our Jersey API (using JAXB adapters that map Currency to the 3 letter ISO currency code, LocalTime to an ISO String, etc)
Note: We also use this custom converter to set not otherwise defined Throwable types to be a plain Object in order to prevent our application's Exception subclass types' inherited property Throwable getSuppressed()
(and with that StackTraceElement[] stackTrace
) from showing up in our Swagger docs. See: https://github.com/swagger-api/swagger-core/issues/1168
Unfortunately this is not exactly what the OverrideConverter provided:
OverrideConverter converter = new OverrideConverter();
converter.add(className, json);
The property was created by using some JSON definition. This way it was also possible to configure the properties as a resource file.
So the additional question is: How do I create a property by parsing some JSON property definition?
@fehguy was this resolved?
Not really - My question above is still open.
Most helpful comment
Unfortunately this is not exactly what the OverrideConverter provided:
The property was created by using some JSON definition. This way it was also possible to configure the properties as a resource file.
So the additional question is: How do I create a property by parsing some JSON property definition?