I have a problem in serialization.
This is my DTO class:
#Data #AllArgsConstructor #NoArgsConstructor
public class ChoicesResponseDTO extends ResponseDTO {
private Long idR;
private ChoicesResponseType choicesResponseType;
private QuestionDTO questionDTO;
}
and this is my scheme from swagger:
ChoicesResponseDTO{
type string
idR integer($int64)
choicesResponseType stringEnum:
Array [ 3 ]
questionDTO QuestionDTO{
idQ integer($int64)
contentQ string
ordreQ integer($int32)
}
}
The problem that if I want to add a new ChoicesDTO, it asks me to add a whole new question in it but I just want to add only the id of the question.
Thanks.
Lombok annotations #AllArgsConstructor #NoArgsConstructor generates constructors for you:
public ChoicesResponseDTO(Long idR, ChoicesResponseType choicesResponseType, QuestionDTO questionDTO)
public ChoicesResponseDTO();
If you want :
public ChoicesResponseDTO(Long idR)
code it yourself or set idR as NonNull or final and add #RequiredArgsConstructor to your class (not compatible with #NoArgsConstructor I guess).
Related
I am calling a third party REST endpoint.
Request sample
{
"body": {
"accountNumber": "12345"
},
"header": {
"username": "someusername",
"password": "somepassword"
}
}
I have created 3 bean classes
MyRequest.java
#Builder
#JsonDeserialize(builder = MyRequest.MyRequestBuilder.class)
public class MyRequest {
#JsonProperty("header")
private MyHeader header;
#JsonProperty("body")
private MyBody body;
}
MyBody.java
#Getter
#Builder
public class MyBody {
private String accountNumber;
}
MyHeader.java
#Getter
#Builder
public class MyHeader {
private String username;
private String password;
}
I'm creating request object using
MyBody body = MyBody.builder().accountNumber("12345").build();
MyHeader header = MyHeader.builder().username("someusername").password("somepassword").build();
MyRequest request = MyRequest.builder().body(body).header(header).build();
Everything is working as expected. The code coverage for MyRequest.java is 100% but my MyBody.java and MyHeader.java is not.
For all the fields I get the error message "Not covered by tests".
Normally I add #Getter and #Setter for Response objects. For request, I just add #Builder annotation.
In this case, if I remove #Getter from MyBody and MyHeader, the third party REST endpoint is getting null values.
It looks like #Getter is invoked when setting the objects to MyRequest.java. But for some reason it is not covered by my test cases.
How to make this work without #Getter or is there a way to cover all the fields (accountNumber, username and password) with #Getter annotation? Any help is appreciated.
Create a lombok.config and add the following attribute to it.
lombok.addLombokGeneratedAnnotation = true
For Maven projects, a file named lombok.config at project’s basedir is the right spot, but other ways/locations may apply, see https://projectlombok.org/features/configuration
You need to instruct Jackson somehow which data should be included during serialization. The default mechanism is to use getters for that purpose.
Replace #Getter with #JsonProperty to get 100% code coverage.
#Builder
public class MyBody {
#JsonProperty
private String accountNumber;
}
This is not my answer. I got this answer from my other post
Why 3rd party REST API's gets null values for request fields when removing #Getter Lombok annotation
Thanks #Alexander Ivanchenko
I have done this before but forgot and couldn't find the answer easily online.
Let's say I have lombok on a POJO like
#Builder
#NoArgsConstructor
class Car {
private int gallons;
private int wheels;
private String name;
}
and I want to use the builder notation in some logic
public Car getCar(boolean isNew) {
<I dont know what type to put here> carBase = Car.builder().wheels(4);
if(!isNew) {
return carBase.gallons(10).build();
}
else {
return carBase.gallons(0).build();
}
}
What type should I use to fill in?
Okay, so I was actually running into this error Why is Lombok #Builder not compatible with this constructor? which was breaking my #Builder class.
Apparently lombok will generate a static nested class in the class annotated with #Builder called <classname>Builder, so to answer my original question there would be a valid class called Car.CarBuilder.
I have this class
public class Hostel extends Hotel<Book> {
}
and this other one
#Data
#AllArgsConstructor
#NoArgsConstructor
#EqualsAndHashCode(of = { "id" })
#SuperBuilder(toBuilder = true)
#JsonInclude(NON_NULL)
public class Hotel<T> {
...
}
but when I do
Hostel hostel = Hostel.builder().build();
I got this compilation error
Required type: Hostel
Provided:
capture of ?
You don't have any annotations on Hostel. Hostel.builder() is really a masquerading Hotel.builder().
So the assignment would have to be
final Hotel<?> build = Hostel.builder().build();
Or more accurately (making static methods subject to inheritance was IMO a mistake)
final Hotel<?> build = Hotel.builder().build();
You probably want to add some Lombok annotations to the child class.
I'm trying to deserialize json objects with the following structure:
{"results":{
"Assessments":{
"Assessment":[
{
"assessor":"",
"buildingName":"Emerald Palace Project",
"certBody":"",
...
The top level is a single entity named "results" which contains "assessments" which are just a list/array of "assessment."
I've tried multiple combinations of mapper configuration such as:
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(DeserializationConfig.Feature.UNWRAP_ROOT_VALUE, true);
But no matter how I switch it up I keep getting a Results object with null Assessments.
Here are my object classes using Lombok.
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
static class Results {
private Assessments assessments;
}
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
static class Assessments {
private List<Assessment> assessments;
}
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
public class Assessment {
private int parentId;
private String stage;
private String notes;
private String rating;
private String scheme;
}
I feel like I must be missing a piece.
Any insight would be greatly appreciated.
Just to be clear: you wrote that
[…] "assessments" which are just a list/array of "assessment."
and your POJOs reflect that... then your JSON has to be…
{"results":{
"Assessments":{
[
{
"assessor":"",
"buildingName":"Emerald Palace Project",
"certBody":"",
...
…instead of…
{"results":{
"Assessments":{
"Assessment":[
{
"assessor":"",
"buildingName":"Emerald Palace Project",
"certBody":"",
...
Watch out for the list directly in "Assessments".
Also mind that your POJO fields are lowercase and so have to be your JSON keys.
So to match POJO with JSON you have various options:
change your JSON keys to lowercase and camelcase
use #JsonProperty("field-name") to match your JSON keys
…
But in each case you have to be aware of the current clash regarding the Assessments/Assessments list.
So because I had to work with the json given to me by the third party API, altering the json was not an option.
Here's how I got this working.
First off I had to change the Assessments object to have a list with a singular name. "assessment" instead of "assessments" as that is how it was spelled in the json response.
#Getter
#Setter
#NoArgsConstructor
static class Assessments {
private List<Assessment> assessment;
}
Also I set up my ObjectMapper to ignore case and unknown properties. Making sure to use com.fasterxml.jackson.databind.ObjectMapper.
private static ObjectMapper getJsonMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
return mapper;
}
The biggest change however was the introduction of a container class.
#Getter
#Setter
#NoArgsConstructor
private static class JsonContainer {
private Results results;
}
This class was required as it held the top level json object "Results."
After these changes were in place I got the Java objects in the state I expected.
I have a document structure which has some generic class. For writing to mongodb everything is fine. But when reading documents from mongodb spring data converts document into object falsely. It converts a subdocument with another type. Both types (actual subcollection type and falsely converted type) are inherit from same abstract class.
Model Classes:(getter setters are generated by lombok )
#Data
public abstract class CandidateInfo {
private String _id;
}
#Data
public class CandidateInfoContainer<E extends CandidateInfo> {
private String _id;
private int commentCount = 0;
#Valid
private List<E> values = new ArrayList<>();
}
#Data
public class Responsibility extends CandidateInfo {
#NotNull
private String responsibilityId;
#ReadOnlyProperty
private String responsibilityText;
}
#Data
public class Experience extends CandidateInfo {
#Valid
private CandidateInfoContainer<Responsibility> responsibilities;
}
#Document
#JsonInclude(JsonInclude.Include.NON_NULL)
#Data
public class Candidate {
private String _id;
#Valid
private CandidateInfoContainer<Experience> experiences;
}
And if you create a mongoRepository like below:
#Repository
public interface CandidateRepository extends MongoRepository<Candidate,String>{
}
And use it like:
#Autowired
private CandidateRepository candidateRepository;
Candidate candidate = candidateRepository.findOne("documentId");
Then spring data mongo mapping converter creates candidates.experiences.responsibilities.values list as Experince list but it should be Responsibility list.
You can find a demo project in this link and more information about the issue. Can anyone point out what is wrong? Otherwise i have to write my own converter(demo has one)
If there is any unclear thing, you can ask.
Thanks.
I open an issue in spring-data-mongo here. Appareantly I caught a bug! Thanks everyone