简体   繁体   中英

Spring Boot + Jackson: Serialize an object in different ways depending on the called REST API

I am developing a Spring Boot web application that exposes REST APIs and I have trouble with JSON Serialization.

Let's say I have two classes A and B, that are in a one-to-many bidirectional relationship.

This means that I have something like this:

public class A {
    private List<B> bList;
    ...
}

and

public class B {
    private A owner;
    ...
}

When it comes to JSON serialize this, of course there is a loop.

And this is my problem:

  • In API methods that focus on A (eg "give me the list of all As in the DB"), I would like a JSON serialization in which:
    • A objects do contain the list of B s
    • B objects do not contain their A owner
  • In API methods that focus on B (eg "give me the list of all B s in the DB"), I would like a JSON serialization in which:
    • A objects do not contain the list of their B s
    • B objects do contain their A owner

I believe I could get it to work with @JsonView annotations, but I do not think it is an elegant solution. In my application (which has more than two classes) I'd need to create and manage at least 4 or 5 JsonViews: so in my model classes, for each attribute I'd have to manage a messy bunch of @JsonView annotations. On the contrary, I believe that model classes should not be aware of the fact that they have different JSON representations depending on the API method.

I searched how to use custom JSON serializers, and found that Jackson allows to do that with its SimpleModule. However it seems that the SimpleModule does not allow to choose which serializer to use on a case-by-case basis (it just always uses the last added Serializer).

So I am a bit clueless now. Does anybody know a clean way to allow the Controllers choose how to serialize a Class?

I think you should use DTO here, you could use different DTO for different endpoints, and you could choose which fields you want to include or exclude. Also, you could decorate them if you need so.

Here you have a list of benefits of using DTO in your endpoints: REST API - DTOs or not?

Use @JsonIdentityInfo

Your question has answer over here: Jackson - serialization of entities with birectional relationships (avoiding cycles)

You can use the @JsonIdentityInfo annotation with entities or use @JsonManagedReference , @JsonBackReference .

You can even ignore one side of the relationship with @JsonIgnore or @JsonView .

If you want to mange serialization / unserialization by yourself, use custom implementations (eg with @JsonDeserialize ).

Eugen provided a nice tutorial on this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM