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.
Related
I have some sensitive domain objects that I would like to convert to json and xml. I am using spring view resolution to do this, but that is beside the point.
I'd like to add annotations to the domain objects to specify which fields should be converted to xml / json.
Something like
#XmlRootElement
public class SensitiveDomainObject {
...
public String getPassword() {...}
#XmlAttribute
#JsonValue
public String getAccountName() {...}
#XmlAttribute
#JsonValue
public String getGoldMemberStatus() {...}
}
I want getAccountName() and getGoldMemberStatus() to be serialised to json and xml, but getPassword to never be serialised.
What I don't want is
1) Separate 'annotation placement strategies' for json and xml as that gets confusing if one needs to markup different methods in different ways as standard.
2) To be explicitly ignoring fields. This is because if some programmer comes along in the future and adds a newly sensitive field without including for example the #JsonIgnore annotation, suddenly that sensitive field is shared.
3) To have to make methods like getPassword() private. I still want to be able to call getPassword() internally.
Has anyone done this or have any thoughts?
EDIT
Included a picture from IBM showing essentially the design I ran with, with explicit DTOs with annotations in the business logic layer. The presentation layer figures out which DTO to request and serve based on the incoming URL.
If you care so much about differentiating what you your business classes are and what is transferred, you may consider implementing a separate package of DTO classes which will explicitly include only those properties you'd like to transfer.
In this case you'll have to explicitly include the transfer properties, this can't happen because the programmer forgot it.
There are other approaches to this like adding some validation rules that the property like password is ignored and enforce them on JAXB context level. But this will only work until someone not knowing will name it kennwort or credentials or whatever may come in mind and your validation rules will be out of effect.
So I see two way:
* Either you trust the programmer (and all the QA/QS process like code reviews etc.) to support her/him.
* Or you make your transfer classes explicit.
For important external interfaces I'd probably go with the second approach (explicit DTOs). If password ends up there, it can't be by forgetting, it will only be on purpose.
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 aware of [JsonIgnore] attribute. Unfortunatelly it ignores property on both, the Request and the Response.
I need a way to ONLY ignore it during RESPONSE. Having to work with two different classes for request and response (even by using inheritance) is not an acceptable solution as it introduces a whole a lot of object copying hassle.
Any help is appreciated.
JsonIgnore instructs the JsonSerializer not to serialize the public field or public read/write property value for both request and response.
It sounds like you have a design issue. Create your request/response data contracts separately and more properly.
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.
We're using interfaces to represent entity classes in our domain model. We have concrete implementations of these by virtue of using LinqToSql. We have added a factory method to each LinqToSql class which our service layer uses to instantiate a new entity (note; as opposed to the controller's DataBind attribute doing it).
MonoRail's default DataBinder implementation will ignore properties that are defined as interfaces.
Ideally, we don't want to instantiate our data-layer classes in MonoRail - the whole point of the interfaces is to separate these concerns.
Also, we don't really want to create another set of non-LinqToSql concrete classes whose only job is to translate between layers.
It's the end of a really long day over here; please can someone have mercy and point us at the parts of IDataBinder that we should overload with our own implementations, or hint at other approaches we might attempt? ;-)
You should be looking at IParameterBinder. take a look at a post I've written on the subject
As Ken pointed, your idea could be implemented with a custom IParameterBinder.
A solution would be to use IOC:
resolve concrete instance of the form from it's interface
then use IDataBinder to bind the instance to the request params
Another one would be using IDictionaryAdapter:
generate a dto proxy for your interface
then use IDataBinder to bind the dto proxy instance to the request params
NB: second option won't work if interface:
is not public (hum)
has methods
or events
or readonly properties
or setonly properties
Last, I'm unsure of what is the problem exposing concrete class in controller's signature.
I myself use concrete form in controllers implementing interface defined in application layer services, it allows me to have concerns separated on both side:
controller side is Http mapping and first level data validation of the form/command
application layer services is business validation and processing of the form/command