In all of my Spring REST Web application, I have a lot of domain objects and DTOs.
I need to filter some domain object or DTOs fields based on the spring security roles of the user who makes the request. I want Jackson to filter the output JSON to allow/disallow specific class fields to be serialized , based on the Spring GrantedAuthorities roles of the user who tries to access the resource.
I can't create new DTO for every different view combination because it would be a mess.
I have found this solution :
Spring 3.2: Filtering Jackson JSON output based on Spring Security role
But it doesn't work, the filter is only applied once, when the first user logins. Then all the other users obtain the same filtering , no matter what their role is.
I cannot explain my problem better than Ray Holland on this blog post :
http://jackson-users.ning.com/forum/topics/jackson-custom-serialization
This is the exact same problem I'm trying to solve for a few days.
I couldn't find a clean way to do that so far.
It's better to use #JsonView in spring project (example)
If #JsonView isn't enough, there isn't easy solution. It is unavoidable to define specific class(interface) to implement #JsonIgnoreProperties and #JsonFilter (
take a look Jackson: Skip Objects Conditionally )
Related
I've been using arrow-kt and spring together a lot lately. I've actually constructed a bridge between the two with several key features, one of which is a spring controller that returns an Either will automatically unwrap it and either handle the exception (Left) or return the result (Right). My long term goal is to publish this as a library.
My latest obstacle is Swagger, or more accurately springdoc openapi. Obviously it is seeing the Either, but i want it to show only the Right value as the success response type. While I know there are annotations where I can set the response model on each controller method individually, I'm trying to avoid this.
My real goal is to setup some global converter so that wherever Swagger sees an Either it will automatically unpack this. I'm just not super familiar with the customization API in Spring doc, and everything I Google just points me to the ApiResponse annotation solution.
How can I define default handling for this type of response?
we are using jackson 2.6.3 in our spring boot project. The domain object needs to be serialized to the user of this app and another internal service. How can I have a field, say 'myField', serialized to 'public_field' for users of our app, and 'internalSvcField' when serialized to the internal service? Eg
myField = "value";
when serialized in different situations,
{..."public_field": "value"...}
and
{..."internalSvcField": "value"...}
any helps/hints are deeply appreciated
You need to use JsonViews for this. It's a feature of Jackson nicely integrated into spring. Check an in-depth tutorial about it here:
https://spring.io/blog/2014/12/02/latest-jackson-integration-improvements-in-spring
Which annotate the relationship allow Jackson to better handle the relation, for save Click ? How change request:
{ "idBanner": 2, "fullnameClient": "Maria"}
#JsonManagedReference, #JsonBackReference,#JsonIdentityInfo,#JsonIgnore...
Working format-request (save Click):
#RequestParam is used to map just request parameters. For example, it will work for requests like POST /sentemail?fullnameClient=vov&idBanner=1
To get request body you should use #RequestBody annotation.
Important notice
I would recommended don't use models (entities) for requests and responses, because it increases a coupling between your business logic and external contract Rest API. For example, in future you will not able to change model without changing of external contract and vise versa.
But if you still want to use entities as request/response body, I would recommend taking a look on Jackson MixIns. It helps to have separate mapping for Jackson and Entities.
I will give an example to better explain my question
my request:
POST
http://localhost:8080/users/
request body: (This gets posted)
{"name":"Matt",
"salary":10000,
"blog_url":"www.myblog.com",
"dept_name":"ENG"
}
class CustomRequest(object):
def __init__(self,name,salary,blog_url,dept_name):
self.name=name
self.salary=10000
self.blog_url=blog_url
self.dept_name=dept_name
models.py
class myUser(models.Model):
//fields -- username, salary
class myUserProfile(models.Model):
User=models.OneToOneField(user)
blog_url=models.URLfield()
dept_name=models.ForeignKey(Department)
#apiview(['POST'])
def createUser(customrequest):
myuser=user(customrequest.name, customrequest.salary)
myuser.save()
myuser.userprofile.blog_url(customrequest.blog_url)
myuser.userprofile.dept_name(customrequest.dept_name)
myuser.save()
I have been most of REST services using Java JAX-RS API. In this framework,
POST request body is automatically deserialized to the object that the method takes in( in the above example, it is customrequest). A developer can define an object with attributes that he is looking for in the POST request and then perform the business logic.
Now that we are thinking of migrating to Django, I am wondering if Django Rest Framework provides this kind of behavior out of box. If so, how would I do that?
Please note, in the JAX-RS world, there is no need for a developer to write a serializer. All that is needed is the transfer object where the incoming JSON gets deserailzed into.
I assume in Django, both a serializer and a transfer object is needed to achieve the same purpose.
In DRF, you have two options:
either you use ModelSerializer and you get the model instance automatically
or you use Serializer and you get the validated_data and do whatever you like with it
The serializer is the same as what you call transfer object, in the sense that both define the data structure and that both will hold the deserialized values.
For models, it is required for persistence, but that is also required in JAX-RS, unless you use the same classes as ORM entities(which is a bad design). So in JAX-RS you will have, for example, CustomRequest and JPA CustomRequestEntity
I am using standard Spring MVC 3x framework and have my model entities all built up with all the good relational stuff (javax.persistence API)... integrated with my DB.
As the application evolved, we needed to support JSON calls.
Given that I have various relationships mapped out in my Model Entity layer,
(classX->classY as well as classY->classX)
I am wondering what the best practice is in translating some of these model classes to appropriate JSON objects without duplicate re-referencing?
eg: Sample buggy response
{"classX":{"id":"1", "classY":{"id":"2", "classX":{"id":"1", "classY":{"id":"2"...
I am contemplating a couple of methodologies I wouldn't mind feedback on...
Keep the existing model classes and set the cross relationships to NULL before putting it into my ModelMap so there won't be some form of re-referencing (me thinks its a HACK)
{"classX":{"id":"1", "classY":{"id":"2", "classX":null}}}
Recreate JSON classes similar to the existing models without the re-referencing classes (but I think that means they will not be as reusable... since I will end up only having classX->classY and not backwards if I wished to drill the other way for a data response).
{"jsonClassX": {"id":"1", "jsonClassY":{"id":"2"}}}
Just simply construct it as standard ModelMap mappings for every controller call. As such no concept of a reusable JSON class, and is dependent on the way the controller constructs and organises the return values. This seems like the easiest, but it means no-reusable code (besides cut and paste)...
{"x":{"id":"1", "y":{"id":"2"}}} // for controller call 1
{"y":{"id":"2", "x":{"id":"1"}}} // for controller call 2
So those are the options I am juggling with at the moment, and I wouldn't mind getting some feedback and some pointers on how others have done it.
You should use Jackson to manage your json marshalling. Then you can add annotations to your model object which tell Jackson how to handle this type of relationship. http://wiki.fasterxml.com/JacksonFeatureBiDirReferences is a good reference for how to set up these relationships.