Response with the parent class in SPRING REST - java

I have implemented a REST API with SPRING REST using Jackson (specifying in the pom.xml with the package org.codehaus.jackson - jackson-mapper-asl - 1.9.13). In the controller I have:
#Controller
#RequestMapping("/test")
public class TestController {
#RequestMapping(value="id", method= RequestMethod.GET)
#ResponseBody
public Parent findById(#PathVariable("id") int id) {
Child child = new Child();
child.setId(id);
child.setName("test");
return child;
}
}
For example in the Parent we could have:
public class Parent {
int id;
public void setId(int id) {
this.id = id;
}
}
And the child:
public class Child extend Parent {
String name;
public void setName(String name) {
this.name = name;
}
}
My problem is that I'd want the response to be only with the parent class and not with the child class (because now the response has the structure of the child).

One solution that would work for you is the following:
#JsonAutoDetect(getterVisibility = JsonAutoDetect.Visibility.NONE)
public class Parent {
#JsonProperty
int id;
public void setId(int id) {
this.id = id;
}
}
I have to admit that this solution is not terribly elegant since you need to add the #JsonProperty annotation to every field in the Parent class, but does have the benefit that no modifications are needed to any of it's subclasses
All the annotations that are present in the jackson library can be found here.
The javadoc for #JsonAutoDetectcan be found here

Related

Deserialization errors in Jackson with duplicated objects with different elements

I'm trying to understand better some deserialization errors I'm seeing in Jackson in a legacy application being converted to a React front-end with Spring back-end.
I see the error when multiple objects of the same class are referenced in the JSON but they have different elements due to fields being ignored with #JsonIgnoreProperties to eliminate infinite recursion. The Spring application will send JSON to the front-end application from the database. We may manipulate a few fields but keep the same basic structure and when we post it back, it says it can't deserialize it. Here's a simplified example.
File named Child.java
public class Child implements java.io.Serializable {
private String name;
#ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private Parent parent;
public Child() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Parent getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
}
File name Parent.java
public class Parent implements java.io.Serializable {
private String name;
#OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL})
#JsonIgnoreProperties("parent")
private Set<Child> children = new HashSet<Child>(0);
public Parent() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Child> getChildren() {
return children;
}
public void setChildren(Set<Child> children) {
this.children = children;
}
}
Controller (normally we would be saving to database here)
#ResponseBody
#RequestMapping(value = "/returnParent", method = RequestMethod.POST)
public ResponseEntity<Parent> returnParent(#RequestBody Child child) throws Exception {
return new ResponseEntity<Parent>(child.getParent(), HttpStatus.OK);
}
JSON posted
{
"name":"child1",
"parent":{
"name":"parent1",
"children":[
{
"name":"child1"
},
{
"name":"child2"
}
]
}
}
Error:
org.springframework.http.converter.HttpMessageNotReadableException:
JSON parse error: No _valueDeserializer assigned; nested exception is
com.fasterxml.jackson.databind.exc.MismatchedInputException: No
_valueDeserializer assigned\n at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 7,
column: 24] (through reference chain:
...Child["parent"]->...Parent["children"]->java.util.HashSet[0]->...Child["name\
I know that if I add this
#JsonIgnoreProperties(value={"children"}, allowGetters=true)
private Parent parent;
to Child that it will suppress the error and ignore child.parent.children but what if we need to be able post back these nested structures? This feels like a bug that it can't read the same JSON it created.

Java Spring Neo4jRepository unable to read a property of abstract type

I have just started experimenting with Neo4J/Java and expect this is an easy one I'm missing, and probably phrasing my queries wrong.
I have some model classes as follows:
#Node
public class Garment {
#Id
#GeneratedValue
private Long id;
private String name;
#Relationship(type = "DESIGNED_BY")
private Entity designer;
// Other properties getters/setters removed for readibility
public Entity getDesigner() {
return designer;
}
public void setDesigner(Entity designer) {
this.designer = designer;
}
}
public abstract class Entity {
#Id
#GeneratedValue
Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
#Node
public class Person extends Entity {
}
#Node
public class Company extends Entity {
}
And a corresponding repository
public interface Garment extends Neo4jRepository<Garment, Long> {
Garment findByName(String name);
}
I have no problem inserting, using repository.save(), this correctly adds everything; nodes, relationships. Fine. It gives Designers of type Person labels of Person, and Designers of type Company the label Company.
However, when I do a find, e.g. findByName(), findAll(). it is not matching the designer and just saying designer is null, according to the cipher being executed/logged it looks like it's trying to build a relationship there with nodes with an Entity label, which there are none.
How can I get my repository to return Garments with designers of Person and Companys. I expect this is going to be as simple as an annotation, in order to fix.
(Note I've tried adding a #Node on the entity type with Person and Company as labels, however it just results in every node being added as both a Person and a Company).

Setter method ignored by Jackson

I have the following Java beans:
public class Customer implements Serializable {
private Integer id;
private String name;
private Country country;
public void setId(Integer id) {
this.id=id;
}
public void setName(String n) {
this.name=n;
}
public void setCountry(Country c) {
this.country=c;
}
public void setCountryId(Integer id) {
this.country= new Country();
this.country.setId(id)
}
//...getters here
}
and
public class Country {
private Integer id;
private String code; //es, us, fr...
private void setId(Integer id) {
this.id=id;
}
//rest of setters and getters
}
and I have the following method:
#RequestMapping(value = "/customer/", method = RequestMethod.POST)
#ResponseBody
public ResponseEntity<Customer> addSecondaryCustomer(#RequestBody Customer sc) {
this.customerService.addCustomer(sc);
return new ResponseEntity<>(sc,HttpStatus.OK);
}
Using the Web Development tools I can see the server is receiving the following:
{
"name": "Pablo Test",
"countryId": 1
}
I can see that the field name is populated, but country remains null. I've tried to set a breakpoint in both setters, but none of them is being called, so it seems that the object mapper is looking for attributes, ignoring setters. ¿Why is this happening?
I am using Jackson 2.9.0 and Spring 4.2.13. It worked with older versions of Spring (4.2.0) and Jackson (2.1.4)
PS: I know I can workaround this by sending "country": { "id": 1} in my AJAX request, but I need to know what's happening here.

Jackson annotation to override the one in parent class

I would like all my objects to have an ID and I wish to serialise it for some child class but not for some others
for example:
public class A {
protected Long id;
..getter and setter
}
public class B extends A {
#Override
#JsonIgnore
public Long getId() {..}
#Override
#JsonIgnore
public void setId(Long id) {..}
}
public class C extends B {
#Override
#JsonInclude
public Long getId() {..}
#Override
#JsonInclude
public void setId(Long id) {..}
}
public class Test {
Set<C> tests ...
..getter setter
}
I have tried serialising Test but the JSON string doesn't include the IDs
If I remove the JsonIgnore from B then in that case the Ids are there.
Is there a way with jackson to archive this?
Use
#JsonIgnore(false)
instead of
#JsonInclude

Overriding #jsonIgnore in subclass

I have a class Parent
public class Parent
{
private int id;
#JsonIgnore
int getId() {}
void setId(int id) {}
}
I have a subclass which is derived from Parent
public class Child extends Parent
{
#JsonProperty // just to explicitly tell jackson to serialize this
#Override
int getId() {}
#Override
void setId(int id) {}
}
I actually don't want the id property to be serialized when an object of Parent is returned but it should be serialized when an object of Child class is returned.
I think if Parent was an Interface, overriding the visibility would work, but I am not sure if the behavior is the same with superclass.
Is there a simple solution for this? I would really appreciate your answers. Tx.
What you want in the Child class is not #JsonProperty but instead #JsonIgnore(false).

Categories