Hi all,
We've set up Swagger UI for a while now (version 1.5.10) on our project but we are trying to find out wether it's possible to integrate the Json root element in the example value.
I see that this problem occurs also in your demo page https://petstore.swagger.io/?_ga=2.186999790.790751393.1601300889-613925661.1599659287
Example:
for the Pet model you display the following Json
{
"id": 0,
"category": {
"id": 0,
"name": "string"
},
"name": "doggie",
"photoUrls": [
"string"
],
"tags": [
{
"id": 0,
"name": "string"
}
],
"status": "available"
}
Where I'm expecting to see:
{
"Pet": {
"id": 0,
"category": {
"id": 0,
"name": "string"
},
"name": "doggie",
"photoUrls": [
"string"
],
"tags": [
{
"id": 0,
"name": "string"
}
],
"status": "available"
}
}
I tried to add @JsonRootName annotation on my entities and set up WRAP_ROOT_VALUE/UNWRAP_ROOT_VALUE on the Json serializer but I still don't get the expected result.
Thank you very much for your help !
Mehdi
Solved! Go to Solution.
I am not sure I fully understand goals and scenarios - also please note that example support and in general customization and extensibility are more advanced in Swagger Core v2 (https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Getting-started, supporting OpenAPI 3.0) - however the example content is not dependent on any serialization preference on the server side, as it is dynamically built by swagger-ui (if an `example` field doesn't exist at Pet level) out of the defined schema.
The schema resolved by swagger-core from Pet Pojo is also not dependent on whatever Jackson mapper serialization options of the Pojo itself (there can be many mapper, each applying or not WRAP_ROOT_VALUE, e.g the one used by the REST framework of choice, the one in use by swagger-core, any other..).
It analyze the properties/members of the Pojo and build a `Model` of it. This model (e.g. a `ModelImpl` object) is then serialized to JSON/YAML along with the whole resolved `Swagger` object to output the serialized resolved Swagger definition.
If the expected JSON accepted (or returned) by your endpoints includes the`Pet` as a property within a "wrapper" (as with Jackson WRAP_ROOT_VALUE) this would need to be defined in the model used, you could for example define a wrapper class and add that as type of the ApiParam or ApiImplicitParam annotation, e.g.
public class PetWrapper{
public Pet pet;
}
As mentioned above, a slightly more complicated alternative is providing an `example` value to the model, to obtain something like:
Pet:
type: "object"
example:
pet:
id: 0
name: "mypet"
properties:
id:
type: "integer"
format: "int64"
name:
type: "string"
unfortunately there is no annotation in Swagger Core v1 allowing to define the example for root models, but you can provide your own along with a custom ModelResolver, e.g.:
class CustomConverter extends ModelResolver {
public CustomConverter(ObjectMapper mapper) {
super(mapper); }
@Override
public Model resolve(JavaType type, ModelConverterContext context, Iterator<ModelConverter> next) {
Model model = super.resolve(type, context, next);
BeanDescription beanDesc = _mapper.getSerializationConfig().introspect(type);
final ExampleAnnotation ann = beanDesc.getClassAnnotations().get(ExampleAnnotation.class);
if (ann != null && !StringUtils.isBlank(ann.value())) {
try {
model.setExample(Json.mapper().readTree(ann.value()));
} catch (JsonProcessingException e) {
e.printStackTrace();
return model;
}
}
return model;
}
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface ExampleAnnotation {
String value() default "";
}
configuring it via service loader or in bootstrap code:
ModelConverters.getInstance().addConverter(new CustomConverter());
you would then be able to define the example for your pojo as you like:
@ExampleAnnotation("{\"Pet\": {\"id\" : 0, \"name\": "...."}}")
public class Pet {
private long id;
private Category category;
...
...
I'm also having the same issues. Is there a way to solve this ?
We are thinking to move away from Swagger if we cannot get an answer to this basic request. Can someone help ?
I am not sure I fully understand goals and scenarios - also please note that example support and in general customization and extensibility are more advanced in Swagger Core v2 (https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Getting-started, supporting OpenAPI 3.0) - however the example content is not dependent on any serialization preference on the server side, as it is dynamically built by swagger-ui (if an `example` field doesn't exist at Pet level) out of the defined schema.
The schema resolved by swagger-core from Pet Pojo is also not dependent on whatever Jackson mapper serialization options of the Pojo itself (there can be many mapper, each applying or not WRAP_ROOT_VALUE, e.g the one used by the REST framework of choice, the one in use by swagger-core, any other..).
It analyze the properties/members of the Pojo and build a `Model` of it. This model (e.g. a `ModelImpl` object) is then serialized to JSON/YAML along with the whole resolved `Swagger` object to output the serialized resolved Swagger definition.
If the expected JSON accepted (or returned) by your endpoints includes the`Pet` as a property within a "wrapper" (as with Jackson WRAP_ROOT_VALUE) this would need to be defined in the model used, you could for example define a wrapper class and add that as type of the ApiParam or ApiImplicitParam annotation, e.g.
public class PetWrapper{
public Pet pet;
}
As mentioned above, a slightly more complicated alternative is providing an `example` value to the model, to obtain something like:
Pet:
type: "object"
example:
pet:
id: 0
name: "mypet"
properties:
id:
type: "integer"
format: "int64"
name:
type: "string"
unfortunately there is no annotation in Swagger Core v1 allowing to define the example for root models, but you can provide your own along with a custom ModelResolver, e.g.:
class CustomConverter extends ModelResolver {
public CustomConverter(ObjectMapper mapper) {
super(mapper); }
@Override
public Model resolve(JavaType type, ModelConverterContext context, Iterator<ModelConverter> next) {
Model model = super.resolve(type, context, next);
BeanDescription beanDesc = _mapper.getSerializationConfig().introspect(type);
final ExampleAnnotation ann = beanDesc.getClassAnnotations().get(ExampleAnnotation.class);
if (ann != null && !StringUtils.isBlank(ann.value())) {
try {
model.setExample(Json.mapper().readTree(ann.value()));
} catch (JsonProcessingException e) {
e.printStackTrace();
return model;
}
}
return model;
}
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface ExampleAnnotation {
String value() default "";
}
configuring it via service loader or in bootstrap code:
ModelConverters.getInstance().addConverter(new CustomConverter());
you would then be able to define the example for your pojo as you like:
@ExampleAnnotation("{\"Pet\": {\"id\" : 0, \"name\": "...."}}")
public class Pet {
private long id;
private Category category;
...
...
Subject | Author | Latest Post |
---|---|---|