Hi everyone I have a question about validate json array request in Spring Boot
This controller
public ResponseEntity<BaseResponse> humanController(#RequestHeader Map<String, String> header,#Valid #RequestBody jsonRequest rqBody) throws ServiceException,Exception {
...
...
}
This jsonRequest Model Request
public class jsonRequest {
#NotBlank
#JsonProperty(value = "name")
private String name;
#NotBlank
#JsonProperty(value = "body")
private bodyModel[] body;
...
...
}
This bodyModel Request
public class bodyModel {
#NotBlank
#JsonProperty(value = "hands")
private String hands;
#NotBlank
#JsonProperty(value = "legs")
private String legs;
#NotBlank
#JsonProperty(value = "head")
private String head;
...
...
}
How can I validate (#Notblank) in bodyModel, I use #NotBlank It not work ?
Related
The browser sends the following object to the backend:
Now I would like to store the data in my database. So I have an entity that looks like this:
#Entity
public class NewQuote {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String description;
#ElementCollection(targetClass = Details.class)
private List<Details> details = new ArrayList<>();
public NewQuote(String description, ArrayList<Details> details) {
this.description = description;
this.details = details;
}
#Embeddable
public class Details {
private String description;
private String label;
public Details(String description, String label) {
this.description = description;
this.label = label;
}
public Details() {}
}
Controller
#PostMapping(value = "/save-quote", produces = MediaType.APPLICATION_JSON_VALUE)
public void saveQuote(#RequestBody Map<String, String> data) {
newQuoteService.saveQuote(data);
}
Service
public void saveQuote(Map<String, String> data) {
JSONObject json = new JSONObject(data);
NewQuote newQuote = new NewQuote(
json.getAsString("description"),
json.getAsString("details")
);
newQuoteRepository.save(newQuote);
}
I am getting an error because json.getAsString("details") should not be a string of course. So how can I turn it to ArrayList<Details>?
Add a DTO to manage your json response. You don't need to explicitly use JSONObject because spring already manage the process of mapping under the wood with Jackson.
Also, it is not a good practice to pass your Entities directly into the controller methods.
NewQuoteDto.java
public class NewQuoteDto {
private Long id;
private String description;
private List<Details> details = new ArrayList<>();
public NewQuoteDto() {
}
// getter and setter or you can use lombok
}
DetailDto.java
public class DetailDto {
private String description;
private String label;
public DetailDto() {}
// getter and setter or you can use lombok
}
Controller
#PostMapping(value = "/save-quote", produces = MediaType.APPLICATION_JSON_VALUE)
public void saveQuote(#RequestBody NewQuoteDto dataDto) {
// here you map dataDto to your model before you call saveQuote
NewQuote data = mapper.map(dataDto, NewQuote.class); // if you use ModelMapper library.
newQuoteService.saveQuote(data);
}
For custom mapping take look here.
I have the below response modal generated from swagger2.0.
Generated(value = "org.openapitools.codegen.languages.SpringCodegen", date = "2022-08-17T22:02:01.513781100-05:00[America/Chicago]")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#JsonProperty("id")
private String id;
#JsonProperty("name")
private String name;
#JsonProperty("city")
private String city ;
#JsonProperty("dateOfBirth")
private String dateOfBirth;
}
when the get User returns the response I would like to skip/Ignore the name and city and wants to return only id and dateOfBirth, how to use JsonIgnoreProperties while converting the response to bodyToMono.
public Mono<User> getUser(String userid) {
return this.webClientConfig
.getWebClient()
.get()
.uri(uriBuilder -> uriBuilder.path("/users/").path(userid).build())
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToMono(User.class)
}
used Jackson2ObjectMapperBuilder
https://www.baeldung.com/jackson-deserialize-json-unknown-properties
In my request body DTO, I want specific fields to be required for one of the API but not for another.
My request body:
#Data
class MyClass {
#NotNull
private String fullName;
#NotNull
private String firstName;
#NotNull
private String lastName;
}
I want fullName to be required for /api/v1 but not for /api/v2. I am using #Valid on request body from javax.validation.
You have to use Spring's #Validated, which is a variant of JSR-303's #Valid. This is used at the method-level:
Controller:
#RequestMapping(value = "apiV1Method")
public String apiV1Method(#Validated(Account. ValidationAPI1.class) MyClassDTO myClassDTO) {...}
#RequestMapping(value = "apiV2Method")
public String apiV2Method(#Validated(Account. ValidationAPI2.class) MyClassDTO myClassDTO) {...}
Object:
class MyClassDTO {
public interface ValidationAPI1 {}
public interface ValidationAPI2 {}
#NotNull(groups = {ValidationAPI1.class})
private String fullName;
#NotNull(groups = {ValidationAPI1.class, ValidationAPI2.class})
private String firstName;
#NotNull(groups = {ValidationAPI1.class, ValidationAPI2.class})
private String lastName;
...
}
I have a Spring Boot app which has a RestController with the following POST method:
#PostMapping(path = "/add", headers = {"content-type=multipart/form-data; charset=utf-8"})
public ResponseEntity<UserWebDTO> addUser(#RequestHeader HttpHeaders headers, #ModelAttribute UserAddDTO userAddDTO) throws Exception {
return new ResponseEntity<>(userService.addUser(userAddDTO), HttpStatus.CREATED);
}
and UserAddDto is as follows:
public class UserAddDTO {
private String first_name;
private String last_name;
private String country_code;
private String phone_number;
private GenderEnum gender;
private String birthdate;
private MultipartFile avatar;
private String email;
}
The code works fine from postman, but I have no idea how to make an integration test with MockMvc for this dto with Multipartfile object, and the test I tried gives me :
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class java.io.ByteArrayInputStream and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: com.user.basic.authentication.dtos.UserAddDTO["avatar"]->org.springframework.mock.web.MockMultipartFile["inputStream"])
any help is appreciated.
Thanks!
I believe that you need to implements Serializable
public class UserAddDTO implements Serializable {
private static final long serialVersionUID = 1L;
private String first_name;
private String last_name;
private String country_code;
private String phone_number;
private GenderEnum gender;
private String birthdate;
private MultipartFile avatar;
private String email;
}
I need to validate a Resource object with #NotBlank annotations in the POST method manually. Is there any way to validate Resource object using Jackson/Spring api. Not sure how to do it.
public class FileMetadataResource extends BaseResource {
#JsonProperty("title")
#NotBlank(groups = {default.class})
#Size(max = 60)
private String title;
#JsonProperty("description")
#Size(max = 255)
#NotBlank
private String description;
}
My custom HandlerMethodArgumentResolver populates the FileMetadataResource
#RequestMapping(method = RequestMethod.POST, consumes = "multipart/related")
#ResponseStatus(HttpStatus.CREATED)
public FileMetadataResource post(FileMetadataResource fileMetadataResource) {
//How to validate fileMetadataResource using jackson here
}
ANy help is appreciated.