TLDR: The problem seems to be that in swagger field should be mandatory when it is enum (Unlike java enum fields). I'm wondering if there is a way to make it optional
I'm using swagger to generate some integration api from yaml files
<groupId>io.swagger</groupId>
<artifactId>swagger-codegen-maven-plugin</artifactId>
<version>2.3.1</version>
(by default Gson implementation is used in plugin for working with json)
In one of yaml files I have a description of request with a field which is described like this
...
definitions:
MyRequest:
type: object
required:
- field1
- field2
properties:
myEnumField:
type: string
enum:
- A
- B
- C
Or see documentation for example.
For that swagger generates public static class Adapter (by default Gson implementation is used in plugin for working with json, so this Adapter extends com.google.gson.TypeAdapter). And this implementation forbid to leave this field empty (fails with NPE in runtime otherwise).
I want to permit optional enum fields for all yaml files, or at least for specified ones.
Thanks in advance
Related
I have this query
http://localhost:8555/list/csv?search={}
Where search is a json object (omitted other params as they are irrelevant here).
How can i convert this into a nested object?
public record CsvParams<T>(
T search,
/* Other query params */ ) {}
Right now im getting error that string cannot be cast into object.
class java.lang.String cannot be cast to class classname
Is there anyway to do this? Old solution uses ObjectMapper to convert string into corresbonding object. I was hoping that maybe there is a way to do it more simpli and remove this boilerplate.
Any single value of a query param can't be automatically converted to a non-primitive type. You can convert multiple params to a class, but not one that happens to be a JSON AFAIK. But you can create a converter custom deserialiser and then use it in different controllers, but in the end you'd still use an ObjectMapper.
More info on how to do the latter here: https://www.baeldung.com/spring-mvc-send-json-parameters
If you have to work with query params than I don't think you can have it converted automatically by Spring boot. But if you work with POST or PUT methods and can pass your params as request params in request body your JSON params can be automatically converted to class instances by Spring boot and no effort required from you. However, if you have to work with query param (say you have to use method GET so you have no request body) than you can use Json-Jackson library or Gson library to parse your Json into class instance. If you use Jackson you will need to use class ObjectMapper. For Jackson lib info see this site, for ObjectMapper class see Javadoc here. However, I wrote my own JsonUtils that is very good for simple usecases like yours. It allows to to parse simple JSON into a class with a single method. It is very simple and strait forward. It is a thin wrapper over Jackson library. See the Javadoc for method readObjectFromJsonString. Class JsonUtils is part of Open Source MgntUtils library. You can get it as Maven artifact on Maven Central and as a jar (with source code and Javadoc) on Github
We have a pojo generated from yml which has #JsonProperty defined on the getter. This is based on maven plugin for openapi. For one such yml, we have a field settlementType. We can't change the name as this is the field to be sent to the vendor in the rest api call. When using jackson's ObjectMapper to deserializa the object, we get the following error -
Conflicting setter definitions for property "settlementType":
settlementType(1 param) vs setSettlementType(1 param).
I tried for a mixin class.
public class SettlementTypeMixin {
#JsonProperty("settlementType"
String settlementType;
#JsonIgnore
public void setSettlementType(String settlementType) {
this.settlementType = settelementType;
}
}
I added the mixin to the mapper using addMixinAnnotations method. But I don't see any change in the behavior.
I also tried setting the fieldVisibility, getterVisibility, setterVisibility and CreatorVisibilities as well. There are other types as well which the yml needs and at the end I have to enable the visibility for all the types mentioned below.
I am not able to get the object mapped using jackson. Please let me know if there is a way out for this.
I use #JsonProperty to serialize data from a JSON through Spring RestTemplate's exchange.
#JsonProperty("ip_address")
public String ipAddress;
#JsonProperty("port")
public Integer port;
I need this property to recognize both upper and lowercase versions of the attribute names i.e. "ip_address" and "IP_ADDRESS" set in #JsonProperty should be recognized.
I have tried the following and none worked:
#JsonFormat(with=JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES) applied on a class level does not work with existing issue reported in GitHub. Also does not work when applied to each attribute in the model class.
use MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES on an ObjectMapper bean.
This example using ObjectMapper and RestTemplate also didn't work even with a combination code with the example on the item before.
All three just have null values for their respective attributes because I disabled error on unknown attributes (a.k.a. the different letter case) for the template.
You can tell jackson to convert all your property names into e.g. SNAKE_CASE variants and set your #JsonProperty accordingly:
Example:
in spring boot set the property in application.properties
spring.jackson.property-naming-strategy=SNAKE_CASE
or you can enable it for just your single class and annotate the class with:
#JsonNaming(PropertyNamingStrategy.SNAKE_CASE.class)
and then set #JsonProperty:
#JsonProperty(vale="ip_address")
I was able to get this working without changing my original pojo class #JsonProperty configs. Using the Object Mapper and Rest Template example you linked to but instead of a Property Naming strategy use the case insensitive mapper feature
ObjectMapper mapper = new ObjectMapper();
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
For Spring Boot App to Ignore Case for JSON attributes names:
Step 1: Make sure your POJO/Domain/Model class has a constructor with respective parameters, and remove any zero arg constructor.
Step 2: Add Jackson lib as a dependency
Ex:
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jaxb-annotations</artifactId>
<version>2.6.5</version>
</dependency>
Step 3: Enable in application.properties file as below
spring.jackson.mapper.accept_case_insensitive_properties=true
I'm using Java Reflection API to get field names and their respective field types from Class objects.
Now I want to map those field types to their corresponding swagger data type.
ie.:
String getSwaggerTypeFromJavaType(..) {
// return swagger type as string
}
I'm working on a project on which Swagger Spec is created manually as a json String by iterating through all the resource classes. Annotating every resource is not an option either. It would be useful if there's an existing library that I could use to do the type conversion.
I'm using swagger-spring-mvc 0.9.5 and have fields like this in my response data:
#ApiModelProperty("Some description")
private List<Account> accounts;
Short version of the question: how can I get from this annotated Java to e.g. Objective C via swagger-codegen?
The swagger JSON that gets generated by that is:
accounts: {
description: "Some description",
items: {
type: "Account"
},
required: false,
type: "List"
}
My colleague is feeding this into swagger-codegen to generate Objective C classes, and it's producing code that doesn't compile.
#property (nonatomic, strong) NSArray<Optional, NSArray> *accounts;
because NSArray (inside the < >) isn't a protocol.
The swagger template files (mustache) create a protocol for each model. When that protocol is specified on an array, it is picked up by JSONModel to generate the correct models from the data inside the list / array. So in this case the expected output is
#property (nonatomic, strong) NSArray<Optional, MAAccount> *accounts;
This will create an NSArray of MAAccount's (Account being the object type and MA being a prefix that swagger already has).
If we hand-edit the swagger JSON to change List to array (as suggested in various similar cases), the output is correct, but we want to avoid this manual step.
So I tried to get swagger-spring-mvc to use "array":
#ApiModelProperty(value = "Some description", dataType = "array")
private List<Account> accounts;
But then discovered that dataType is ignored in swagger-spring-mvc 0.9.5, and by the looks of it, in springfox 2.0 it is ignored unless it's a fully-qualified Java class name.
Is there a way to achieve this, either by getting swagger-spring-mvc/springfox to use "array" or by any other means?
For the most part the swagger annotations are only an aid to the springfox engine to infer additional information about the types like description/hidden/readonly etc that are not otherwise available from the type system. It can also used as a crutch to represent types that are not easily inferred. Data types can be overriden, but just for type safety as it was pointed out in the comment.
Specifically, I read that dataType will be ignored unless it's a fully-qualified class name.
Like #CupawnTae suggested, version 2.x of springfox supports an option to render generic types with code-generation friendly and language agnostic representations of generic types.
When creating/configuring your docket you will need to specify that the rendered swagger service description needs to be code-generation friendly using the forCodeGeneration option
#Bean
public Docket docket() {
return new Docket(DocumentationType.SWAGGER_2)
...
.forCodeGeneration(true)
...;
}
This will cause springfox to render generic types like List<String>
as ListOfString when forCodeGeneration is set to true
as ListĀ«StringĀ» when forCodeGeneration is set to false
You can try notation below. Dont't forget to use package info of you class
#ApiModelProperty(dataType = "[Lyour.package.Account;")
private List<Account> accounts;