Reputation: 6494
I'm designing REST API for many resources I need to maintain at least 2 representations of the same format (e.g. JSON) which only differ in the amount of data they expose.
For example, I have books, publishers and authors which I'm exposing via REST. So I have 3 collection of resources:books
, publishers
and authors
.
When requesting a book I want it to include minimum information about its authors and publishers - just names, ids and hyperlinks to their full representation.
GET /books/12345
200 OK
{
id: "12345",
title: "My Book",
authors: [
{id:"111", name:"J. Smith", _href:"/authors/111"},
{id:"222", name:"J.R.R. Tolkien", _href:"/authors/222"}
],
publisher: {id:"333", name:"HarperCollins", _href:"/publishers/333"},
}
When user requests, e.g. /publishers/333
it should get more info about it, not just name and id:
{
id: "333",
name: "HarperCollins",
address : { ... },
contact : { ... },
logo : { ... }
}
In my application I have 3 classes Book
, Publisher
and Author
, where Book
contain publisher and collection of authors. And I'm using Jackson and Spring MVC to expose all the entities as JSON via REST API.
@RequestMapping("/books/{id}")
@ResponseBody
public Book getBook(String id) {
return getBookById(id);
}
@RequestMapping("/authors/{id}")
@ResponseBody
public Book getAuthor(String id) {
return getAuthorById(id);
}
Now the questions:
AuthorReference
and Author
, PublisherReference
and Publisher
).Upvotes: 2
Views: 706
Reputation: 1
1/ According to Spring MVC documentation, to serialize your object over HTTP you have to define your own class implementing HttpMessageConverter<T>
with T
either Book
, Publisher
or Author
.
http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/remoting.html#rest-message-conversion
2/ It is not necessary to split your objects in two. The logic to select what fields you pick up from an Author
is contained in the AuthorToHttp implement HttpMessageConverter<Author>
. Just need to develop a AuthorReferenceToHttp implement HttpMessageConverter<Author>
to use when you want less data to be send over HTTP.
Another solution could be either AuthorReference extend Author
or Author extend AuthorReference
on one hand and AuthorToHttp implement HttpMessageConverter<Author>
with AuthorReferenceToHttp implement HttpMessageConverter<AuthorReference>
on the other hand to serialize your Author
.
3/ Inheritance/Generalization is enough. Not necessarily a need for a pattern.
Composite is a wrong choice, you don't need a tree structure. According to circumstances you want either all data about an author - default behavior -, or the main data about an author - "proxied" behavior -. Proxy would be a better choice.
4/ No idea.
Upvotes: 0
Reputation: 11495
Have you considered using a more standard hypermedia format, such as HAL?
Doing so, it becomes pretty clear that you would have a difference between resources, and links to other resources. For example, it might end up as:
GET /books/123
200 OK
{
"id": "123"
"title": "My Book"
"_links": {
"author": [
{ "href": "/authors/111", "title": "J. Smith" },
{ "href": "/authors/321", "title": "Jules Verne" }
],
"publisher": { "href": "/publishers/123", "title": "Harper Collins" }
}
}
In terms of implementation, I would say you can either:
Create custom DTO classes for each resource representation, along the lines of:
public class BookDto {
@JsonProperty(value="_links")
public LinkCollection getLinks() { }
public String getTitle() { }
}
Use the same classes, but use filters to modify the objects before Jackson serializes, and use some combination of @JsonProperty/@JsonIgnore.
Upvotes: 2