Spring Boot REST display id of parent only in a JSON response - json

Assume I have the following class:
public class ChildEntity {
...
#ManyToOne
private ParentEntity parent;
...
}
Now, I have a REST endpoint that retrieves a child entity object from the database, thus my JSON is the following:
{"id": "123", "name":"someName", "parent": { //parent fields here } ... }
I want to format my JSON responses in another way. I want parent display only the id from the database, instead of the whole object:
{"id": "123", "name":"someName", "parentId": "1" ... }

Basically returning entities directly from endpoints isn't a good idea. You make very tight coupling between DB model and responses. Instead, implement a POJO class that will be equivalent of the HTTP response you sent.
This POJO will have all ChildEntity fields and parentId only and will be constructed in HTTP layer.
Please, see the discussion in comments, basically such an object returned from web layer is not a DTO according to me.

I am annotating #JsonIgnore which ever field I do not want to be part of JSON response. Creating parallel POJO for each entity is costly affair.
#JsonIgnore
#NotNull
#Column(name="DELETED")
private boolean deleted = false;

Related

How to accept json data though post in spring boot rest

PostMapping method
#RestController
#RequestMapping("/validate")
public class Validatesimapi {
#PostMapping
public Simoffers validateSim(#RequestBody ???)
}
I want to pass following json object through post request and accept it in validateSim. What should I write at ???.
{
"id": "1234",
"num":"2343335"
}
both the datatypes of id and num is String.
enter code here
It’s as simple as adding a DTO with the fields that you want. The Jackson mapper will map the json to that object.

Validation of JSON Object With #Valid and #Requestbody in SpringBoot

I am trying to validate a JSON body within a post method. Here is a sample code:
#PostMapping(value = "GetInfo")
public ResponseEntity<Person> getOffers(#Valid #RequestBody InfoRequest infoRequest) {
//generate person response according to inforequest JSON.
Person person = PersonGenerator.getOffers(infoRequest);
return new ResponseEntity<>(person, HttpStatus.OK);
}
When I send JSON body to get info (for ex: Name and Age) I want the program to throw an error if some extra fields are entered that are not needed for the Person class. As an example in below ExtraField. But #RequestBody and #Valid annotations are just checking for fields that have a match. Since it is filtered (afaik in this case ExtraField is filtered) I can't get full JSON to analyze infoRequest to find if any extra information was sent.
{
"Name": "sample",
"Age": "sample",
"ExtraField": "prevent",
}
I know there are some libraries to check JSON files. But first I have to know what is coming :).
If there is no annotation to see extra fields entered. How can I extract and analyze JSON file*
Note: Changing parameter type infoRequest as String is not an option for security purposes.
By default, the Spring Boot configuration will disables Jackson DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES feature. One possible solution could be enabling it again in you application.yml file as follows:
spring.jackson.deserialization.fail-on-unknown-properties=true
This will change the behaviour for Jackson ObjectMapper if you want finer-grained configuration you might use #JsonIgnoreProperties(ignoreUnknown = false) as follows:
#JsonIgnoreProperties(ignoreUnknown = false)
public class InfoRequest {
(...)
}

Spring Rest: Mapping a property of a bean as nested JSON

My Spring REST controller needs to map an object parameter that looks like this:
{
"batchId": 43091,
"domain": "XX",
"code": "XXX",
"effectiveDate": "2020-02-13",
"status": "Y",
"result": [{"ruleName":"name",...]}]
}
I'm having trouble coming up with the DTO to convert this data into. What I have so far looks like this:
#Data
#NoArgsConstructor
#EqualsAndHashCode
public class ValidationResult {
private String result;
private String status;
private String batchId;
private String domain;
private String code;
private String effectiveDate;
}
But result, which contains the embedded JSON, is always null. I don't care about that JSON being mapped, as I'm storing it as a JSON type in the database (Postgresql). But what Java type do I need to declare it to be to get the controller to convert it? I tried making it a javax.json.JsonObject, but that failed.
What we always do with those json inputs is to map those to specific classes. Which means, in your case, result could be a class which itself contains the given fields "ruleName" and their types. Then your Validaton Result containts a private Result result. If naming conventions are quite right the used mapper will be able to convert and map the response to the class and its properties.

Object modelling - REST vs Hibernate

I am facing this in a project of my own, but i am sure this should be a generic issue.
I am trying to build rest services using java, spring and hibernate.
My typical entity object is modeled like below
#Entity
public class Company implements Serializable{
private Long companyId;
private String name;
private String shortDescription;
private Long logoId;
private Set<ActivityType> activityTypeList;
private String address;
private RegistrationInfo regInfo;
}
Where one object has associations with other objects, so my model object contains references to the associated objects.
I use jackson configured with spring for json-object and object-json conversion, it works perfectly, so I am good till this point.
Now I want my POST calls(which I am using for object creation) to create Company objects, only catch here is that I do not want to pass complete json for contained objects(like ActivityType and RegistrationInfo in above example), rather an id for each where the object with provided id already exists in the database. For example see this JSON snippet:
{
"companyId": 5,
"name": "test company created by rest call",
"shortDescription": "dummy description",
"logoId": 0,
"activityTypeList": [
{"activityTypeId": 1}
],
"address": "202, kardoga lane, lonavala, Maharashtra",
"regInfo": {
"registrationInfoId": 1
}
}
My rest service just needs to associate the newly created company object with the existing contained object with the provided id(inside POST call's body).
Jackson serialization creates unpopulated objects in this case, which hibernate fails to persist (for obvious reasons, there is no data just an id)
Sure i can use a DTO over here, i can get REST -> DTO and then DTO -> entity, but that seems an overhead and moreover in order to populate the Company object defined above, I will need to fetch the associated objects first from DB, attach them to my company object and then save it back. That will be an unnecessary DB trip.
Anyone has better idea on this one? Any design pattern, framework or simple tips/tricks in which i dont require a dto as well as save DB calls.

How to parse json arrary?

I have come across a problem of parsing json data . I am building project using spring boot based on REST api . When i have to parse data corresponding to domain then it is very easy , i use RequestBody in controller method with domain name but in current scenerio i have a list of domain in json form :
{
"data":[
{
"type":"abc",
"subtypes":[
{
"leftValue":"BEACH",
"rightValue":"MOUNTAIN",
"preferencePoint":60
},
{
"leftValue":"ADVENTURE",
"rightValue":"LEISURE",
"preferencePoint":60
}
]
},
{
"type":"mno",
"subtypes":[
{
"leftValue":"LUXURY",
"rightValue":"FUNCTIONAL",
"preferencePoint":60
},
{
"leftValue":"SENSIBLE",
"rightValue":"AGGRESIVE",
"preferencePoint":0
}
]
}
]
}
I am sending data in list where type is the property of class Type
and class Type has list of Subtypes class and subtype class contains leftValue and rightValue as enums
I am using spring boot which uses jackson liberary by default and i want to parse this data into corresponding Type class using Jackson. Can any one provide me solution.
It wasn't clear to me if you have static or dynamic payload.
Static payload
For static one, I would personally try to simplify your payload structure. But your structure would look like this. (I skipped getters and setters. You can generate them via Lombok library).
public class Subtype{
private String leftValue;
private String rightValue;
private int preferencePoint;
}
public class Type{
private String type;
private List<Subtype> subtypes;
}
public class Data{
private List<Type> data;
}
Then in your controller you inject Data type as #RequestBody.
Dynamic payload
For dynamic payload, there is option to inject LinkedHashMap<String, Object> as #RequestBody. Where value in that map is of type Object, which can be casted into another LinkedHashMap<String, Object> and therefore this approach support also nested objects. This can support infinite nesting this way. The only downside is that you need to cast Objects into correct types based on key from the map.
BTW, with pure Spring or Spring Boot I was always able to avoid explicit call against Jackson API, therefore I don't recommend to go down that path.