rfsbsb
rfsbsb

Reputation: 519

Best way to convert a JPA entity to REST representations using JAX-RS and Jackson

I'm looking for a way to export some JPA entities to a REST API, but instead of sending the whole entity every time I want to share just some specific fields depending of the entry point. Here's a small example:

Say we have an Author class with few fields:

@Entity
public class Author implements Serializable{

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = SEQUENCE)
    private Long id;

    @NotNull
    @Size(min = 1, message = "{required.field}")
    private String name;

    @NotNull
    @Size(min = 1, message = "{required.field}")
    private String country;

    private LocalDate birthDate;

    // getters and setters
}

And say we have this REST service (just two methods):

@Path("authors")
public class AuthorREST {

    @Inject
    private AuthorBC bc;

    @GET
    @Produces("application/json")
    public List<Author> find(@QueryParam("q") String query) throws Exception {

        List<Author> result;

        if (Strings.isEmpty(query)) {
            result = bc.findAll();
        } else {
            result =  bc.find(query);
        }
        return result;
    }

    @GET
    @Path("{id}")
    @Produces("application/json")
    public Author load(@PathParam("id") Long id) throws Exception {

        Author result = bc.load(id);

        if (result == null) {
            throw new NotFoundException();
        }

        return result;
    }
}

Now, this way, I'll always have the 4 fields when my API is called.

I understand that if I use Jackson I can set an @JsonIgnore to fields I want to ignore, and they will always be ignored.

But what if I want that, in some cases, my whole entity is returned by one service, and in other service (or other method in the same service), only 2 or 3 fields are returned?

Is there a way to do it?

Upvotes: 5

Views: 5912

Answers (5)

Alexander Petrov
Alexander Petrov

Reputation: 9492

If you want to decouple the parsing from your JPA entities and return only certain attributes you can always use Mixins for this purpose. http://www.cowtowncoder.com/blog/archives/2009/08/entry_305.html https://github.com/FasterXML/jackson-docs/wiki/JacksonMixInAnnotations

One more thing. If you want things to be dynamic in one service to return one representation in another to return another representation. Your option is to write a custom JSON serializer! Check this post for how to create a customer serializer: How do I use a custom Serializer with Jackson?

Upvotes: 3

Beezer
Beezer

Reputation: 1108

I would use Spring Data REST and then use the ApiModel annotation to hide the attributes you do not want exposed.

Upvotes: 0

cassiomolin
cassiomolin

Reputation: 131187

@JsonView and mix-in

You already know you can use annotations such as @JsonIgnore and @JsonIgnoreProperties to make Jackson ignore some properties.

You also could check the @JsonView annotation. For some details on how to use @JsonView with JAX-RS, have a look here.

If modifying the JPA entities is not an option, consider mix-in annotations as described in this answer.

Data Transfer Object

Data Transfer Object (DTO) is a pattern that was created with a very well defined purpose: transfer data to remote interfaces, just like webservices. This pattern fits very well in REST APIs and using DTOs you'll have more flexibility in the long run. You can have tailored classes for your needs, once the REST resource representations don't need to have the same attributes as the persistence objects.

To avoid boilerplate code, you can use mapping frameworks such as MapStruct to map your REST API DTOs from/to your persistence objects.

For details on the benefits of using DTOs, check the following answers:

To give better names to your DTOs, check the following answer:

Upvotes: 5

Stan
Stan

Reputation: 1430

For myself I found it quite suitable to use @JsonView annotation. So you can define fields to be rendered in specific view. You can find more info here http://wiki.fasterxml.com/JacksonJsonViews

Upvotes: 1

Thamizharasu
Thamizharasu

Reputation: 331

I think you can write a custom MessageBodyWriter using Jersey framework and you can control the response payload the way you want. Here you have to write few lines of code in-order to manage the response payload. For more information please visit https://jersey.java.net/documentation/latest/message-body-workers.html#d0e6826

Upvotes: 0

Related Questions