Difference Between @JSONignore and @JSONbackreference, @JSONmanagedreference

Difference between @JsonIgnore and @JsonBackReference, @JsonManagedReference

Lets suppose we have

private class Player {
public int id;
public Info info;
}
private class Info {
public int id;
public Player parentPlayer;
}

// something like this:
Player player = new Player(1);
player.info = new Info(1, player);

Serialization

@JsonIgnore

private class Info {
public int id;
@JsonIgnore
public Player parentPlayer;
}

and @JsonManagedReference + @JsonBackReference

private class Player {
public int id;
@JsonManagedReference
public Info info;
}

private class Info {
public int id;
@JsonBackReference
public Player parentPlayer;
}

will produce same output. And output for demo case from above is: {"id":1,"info":{"id":1}}

Deserialization

Here is main difference, because deserialization with @JsonIgnore
will just set null to the field so in our example parentPlayer will be == null.

Sample Image

But with @JsonManagedReference + @JsonBackReference we will get Info referance there

Sample Image

JsonManagedReference vs JsonBackReference

@JsonManagedReference is the forward part of reference – the one that
gets serialized normally. @JsonBackReference is the back part of
reference – it will be omitted from serialization.

So they really depend on the direction of your relationship

public class User {
public int id;
public String name;

@JsonBackReference
public List<Item> userItems;
}

public class Item {
public int id;
public String itemName;

@JsonManagedReference
public User owner;
}

JsonIgnore and JsonBackReference are being Ignored

i found a way by annotating the setter by @Transient

idont know why but it works fine

User.class

    //i get that suggestion from some sites
@JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
@Entity
@Table(name = "user", catalog = "someSchema")
public class User implements java.io.Serializable {

private String name;
private String password;
private String username;
private Set<Telephone> telephones = new HashSet<Telephone>(0);

@OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
public Set<Telephone> getTelephones() {
return this.telephones;
}

public void setTelephones(Set<Telephone> telephones) {
this.telephones = telephones;
}
}

Telephone.class

   @Entity
@Table(name = "telephone", catalog = "someSchema")
public class Telephone implements java.io.Serializable {

private User user;
private String telephone;

@ManyToOne(fetch = FetchType.LAZY)

@JoinColumn(name = "user_id", nullable = false)
public User getUser() {
return this.user;
}

@Transient
public void setUser(User user) {
this.user = user;
}

}

Another Naive Solution

I solved it manually in my RESTful Controller

by loop over the set of telephones and set user to null

    @RestController
@RequestMapping("/user")
public class UserController extends ParentController {

static final Logger logger = Logger.getLogger(UserController.class.getName());
@Autowired
IUserDao iuserdao;

@RequestMapping(value = "/signin", method = RequestMethod.POST)
public ResponseEntity<User> signin(@RequestBody LoginWrapper login) {
System.out.println("==============GET USER==============");
try {
User user = iuserdao.signin(login);
if (user == null) {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.set(ERR_HEADER_NAME, "user not exist");
return new ResponseEntity<User>(httpHeaders, HttpStatus.NOT_FOUND);
} else {
List<Telephone> tels=user.getTelephones();
for (Telephone telephone : tels) {
telephone.setUser(null);
}
return new ResponseEntity<User>(user, HttpStatus.OK);
}

} catch (Exception e) {
System.out.println(e.getMessage());
return null;
}

}

still need a better answer concerning Jackson problem..

How to map OneToOne relationship between POJOs using @JsonManagedReference and @JsonBackReference

You can think of it as just a special case of one-to-many; so you will annotate reference from 'parent' to 'child' as @JsonManagedReference, and 'child' to 'parent' as @JsonBackReference.

One more document that might be helpful is the one at FasterXML Jackson Wiki; first example is for one-to-one relationship, and should be applicable for your case.

Hibernate and Jackson manyToMany relation with extra fields

Finally, I solved my problem. Instead of using a composite key, I changed my database model to use a primary id key and 2 references to my concerned tables. Mapping is easier and I get my information.

Json and Java - Circular Reference

There are two ways you can go about this. If you must expose your entity to the outside world, I recommend adding @JsonIgnore on the property that is causing the circular reference. This will tell Jackson not to serialize that property.

Another way is to use the bidirectional features provided by Jackson. You can either use @JsonManagedReference or @JsonBackReference. @JsonManagedReference is the "forward" part of the property and it will get serialized normally. @JsonBackReference is the "back" part of the reference; it will not be serialized, but will be reconstructed when the "forward" type is deserialized.

You can check out the examples here.

This addresses your comment: I think what you might want to do in this case is use a DTO that is visible to the outside world. I like this approach because I don't want to expose my entities to the outside. This means that the Jackson annotations would be on the DTO and not on the enity. You would need some sort of mapper or converter that converts the entity to the DTO. Now when you make changes to your entity, they won't get propagated to the DTO unless you modify your mapper/converter. I think this is ok, because when you make a change to your entity you can decide if you want that change to be exposed or not.

UPDATE

There is a good blog post here that goes into detail about the various ways you can handle bidirectional relationships in Jackson. It describes solutions that use @JsonIgnore, @JsonManagedReference and @JsonBackReference, @JsonIdentityInfo, @JsonView and a custom serializer as well. It's a pretty comprehensive writeup of the various techniques that you can use.



Related Topics



Leave a reply



Submit